TRANWRD doesn't replace properly - string

I was trying to progressively remove each /* */ comment pair on the same line by using the tranwrd function. However, the replacement doesn't happen for some reason.
Here's the code:
data _null_;
str="/* Comment 1 */ /* Comment 2 */ /* Comment 3 */ /* Comment 4 */";
do while(1);
startc=find(str,"/*");
endc=find(str,"*/");
put startc endc;
if startc = 0 then leave;
else do;
temp=substr(str,startc,endc-startc+2);
put "temp: " temp;
str=tranwrd(str,temp,"");
put "str: " str;
end;
end;
run;
The code goes into infinite loop because although temp gets the value of "/* Comment 1 */", TRANWRD is unable to make a replacement for some reason.

You need to TRIM the argument for finding (temp). Otherwise it has extraneous spaces on the end. Remember, string variables in SAS always have their full length - so if it is a 200 long string with "ABCDE" in it, it really is "ABCDE " (up to 200).
data _null_;
str="/* Comment 1 */ /* Comment 2 */ /* Comment 3 */ /* Comment 4 */";
do while(1);
startc=find(str,"/*");
endc=find(str,"*/");
put startc endc;
if startc = 0 then leave;
else do;
temp=substr(str,startc,endc-startc+2);
put "temp: |" temp "|";
str=tranwrd(str,trim(temp),"");
put "str: " str;
end;
end;
run;
See the | | around temp; it has at least one extra space around it. Your example was fortuitous in that you incorrectly added 2 to the length (should add one); since all of your temp arguments are identical in length this wouldn't have come up if you had added 1, but in a real world example this is presumably not the case.
Further, if you want it replaced with nothing, as opposed to a single space, you need to use TRANSTRN and TRIMN (which I think are 9.2+). The above code really replaces it with a single space. SAS does not have a concept of "", character null/missing is always " ". TRIMN and TRANSTRN allow you to make this replacement as a sort of workaround.

Related

JPEG Huffman "DECODE" Procedure

The JPEG standard defines the DECODE procedure like below. I'm confused about a few parts.
CODE > MAXCODE(I), if this is true then it enters in a loop and apply left shift (<<) to code. AFAIK, if we apply left shift on non-zero number, the number will be larger then previous. In this figure it applies SLL (shift left logical operation), would't CODE always be greater than MAXCODE?
Probably I coundn't read the figure correctly
What does + NEXTBIT mean? For instance if CODE bits are 10101 and NEXTBIT is 00000001 then will result be 101011 (like string appending), am I right?
Does HUFFVAL list is same as defined in DHT marker (Vi,j values). Do I need to build extra lookup table or something? Because it seems the procedure used that list directly
Thanks for clarifications
EDIT:
My DECODE code (C):
uint8_t
jpg_decode(ImScan * __restrict scan,
ImHuffTbl * __restrict huff) {
int32_t i, j, code;
i = 1;
code = jpg_nextbit(scan);
/* TODO: infinite loop ? */
while (code > huff->maxcode[i]) {
i++;
code = (code << 1) | jpg_nextbit(scan);
}
j = huff->valptr[i];
j = code + huff->delta[i]; /* delta = j - mincode[i] */
return huff->huffval[j];
}
It's not MAXCODE, it's MAXCODE(I), which is a different value each time I is incremented.
+NEXTBIT means literally adding the next bit from the input, which is a 0 or a 1. (NEXTBIT is not 00000001. It is only one bit.)
Once you've found the length of the current code, you get the Vi,j indexing into HUFFVAL decoding table.

Read binary file data in Verilog into 2D Array

I have an array that I want to load up from a binary file:
parameter c_ROWS = 8;
parameter c_COLS = 16;
reg [15:0] r_Image_Raw[0:c_ROWS-1][0:c_COLS-1];
My input file is binary data, 256 bytes long (same total space as r_Image_Raw). I tried using $fread to accomplish this, but it only works through the 4th column of the last row:
n_File_ID = $fopen(s_File_Name, "r");
n_Temp = $fread(r_Image_Raw, n_File_ID);
I also tried using $fscanf for this, but I get an error about packed types when opening the synthesis tool:
while (!$feof(n_File_ID))
n_Temp = $fscanf(n_File_ID, "%h", r_Image_Raw);
I feel like this should be easy to do. Do I have create a 2D for loop and loop through the r_Image_Raw variable, reading in 16 bits at a time? I feel like it should not be that complicated.
I realized my mistake. It should be:
n_File_ID = $fopen(s_File_Name, "rb");
n_Temp = $fread(r_Image_Raw, n_File_ID);
I was using "r" and not "rb" to specify that it was a binary file. Interestingly enough, "r" does work for the majority of the data, but it is unable read in the last ~13 locations from the file.
Try this.
f_bin = $fopen(s_File_Name,"rb");
for (r = 0; r < c_ROWS; r = r+1) begin
for (c = 0; c < c_COLS; c = c+1) begin
f = $fread(r16,f_bin);
r_Image_Raw[r][c] = r16;
end
end
See that $fread(r16,f_bin) first param is reg, second - file!
Below an example for reading from a binary file with systemverilog.
As shown in IEEE SV Standard documentation, the "nchar_code" will return the number of bytes/chars read. In case EOF have been already reached on last read this number will be zero.
Please, notice that "nchar_code" can be zero but EOF has not been reached, this happens if you have spaces or returns at the end of the data file.
You can control the number of bytes to be read with the $fread function. This is done with the type definition of the "data_write_temp" or "mem" of the below examples. If the "data_write_temp" variable is 16bits long then it will read 16bits each time the $fread is called. Besides, $fread will return "nchar_code=2" because 16bits are 2bytes. In case, "data_write_temp" is 32bits as in the example, the $fread will read nchar_code=4bytes(32bits). You can also define an array and the $fread function will try to fill that array.
Lets define a multidimensional array mem.
logic [31:0] mem [0:2][0:4][5:8];
In the example word contents, wzyx,
-w shows the start of the word
-z corresponds to words of the [0:2] dimension (3 blocks).
-y corresponds to words of the [0:4] dimension (5 rows).
-x corresponds to words of the [5:8] dimension (4 columns).
The file will be structure as below (notice #z shows the z dimension blocks):
#0 w005 w006 w007 w008
w015 w016 w017 w018
w025 w026 w027 w028
w035 w036 w037 w038
w045 w046 w047 w048
#1 w105 w106 w107 w108
w115 w116 w117 w118
w125 w126 w127 w128
w135 w136 w137 w138
w145 w146 w147 w148
#2 w205 w206 w207 w208
w215 w216 w217 w218
w225 w226 w227 w228
w235 w236 w237 w238
w245 w246 w247 w248
In the previous structure, the numbers shows the index of each dimension.
e.g. w048 means, the word w (32bits) value on index z =0, index y= 4 and index x= 8.
Now, you have many ways to read this.
You can read all in a single shot using the type "mem" declared above, or you can do a while loop until EOF reading pieces of 32bits using a "data_write_temp" variable of 32bits. The loop is interesting if you want to do something some checks for every word piece and you are not interested having a memory value.
In case multidimensional array / single shot read is chosen, then you can either use $fread or use an specific function $readmemh defined in SV standard.
$readmemh("mem.data", mem, 1, (3*5*4));
is equivalent to
$readmemh("mem.data", mem);
The $readmemh spare you the need to open/close the file.
If you use $fread for one shot read
logic [31:0] mem [0:2][0:4][5:8];
register_init_id = $fopen("mem.data","rb");
nchar_code = $fread(mem, register_init_id);
if (nchar_code!=(3*5*4)*4)) begin
`uvm_error("do_read_file", $sformatf("Was not possible to read the whole expected bytes"));
end
$fclose(register_init_id);
In case you wanted to do a loop using 32b word read. Then see the following example.
The example uses the data which is read from the file to write to AHB Bus using an AHB Verification Component.
logic [31:0] data_write_temp;
...
//DO REGISTER FILE
register_init_id = $fopen("../../software/binary.bin","rb");
if (register_init_id==0) begin `uvm_error("do_read_file", $sformatf("Was not possible to open the register_init_id file")); end
count_32b_words=0;
while(!$feof(register_init_id)) begin
nchar_code = $fread(data_write_temp, register_init_id);
if ((nchar_code!=4)||(nchar_code==0)) begin
if (nchar_code!=0) begin
`uvm_error("do_read_file", $sformatf("Was not possible to read from file a whole 4bytes word:%0d",nchar_code));
end
end else begin
tmp_ahb_address = (pnio_pkg::conf_ahb_register_init_file_part1 + 4*count_32b_words);
data_write_temp = (data_write_temp << 8*( (tmp_ahb_address)%(DATAWIDTH/(8))));//bit shift if necessary not aligned to 4 bytes
`uvm_create_on(m_ahb_xfer,p_sequencer.ahb0_seqr);
assert(m_ahb_xfer.randomize(* solvefaildebug *) with {
write == 1;//perform a write
HADDR == tmp_ahb_address;
HSIZE == SIZE_32_BIT;
HBURST == HBURST_SINGLE;
HXDATA.size() == 1; //only one data for single bust
HXDATA[0] == data_write_temp;
}) else $fatal (0, "Randomization failed"); //end assert
`uvm_send(m_ahb_xfer);
count_32b_words++;
end //end if there is a word read
end //end while
$fclose(register_init_id);

Read a String with spaces till a new line in C

I am in a pickle right now. I'm having trouble taking in an input of example
1994 The Shawshank Redemption
1994 Pulp Fiction
2008 The Dark Knight
1957 12 Angry Men
I first take in the number into an integer, then I need to take in the name of the Movie into a string using a character array, however i have not been able to get this done.
here is the code atm
while(scanf("%d", &myear) != EOF)
{
i = 0;
while(scanf("%[^\n]", &ch))
{
title[i] = ch;
i++;
}
addNode(makeData(title,myear));
}
The title array is arbitrarily large and the function is to add the data as a node to a linked list. right now the output I keep getting for each node is as follows
" hank Redemption"
" ion"
" Knight"
" Men"
Yes, it oddly prints a space in front of the cut-off title. I checked the variables and it adds the space in the data. (I am not printing the year as that is taken in correctly)
How can I fix this?
You are using the wrong type of argument passed to scanf() -- instead of scanning a character, try scanning to the string buffer immediately. %[^\n] scans an entire string up to (but not including) the newline. It does not scan only one character.
(Marginal secondary problem: I don't know from where you people are getting the idea that scanf() returns EOF at end of input, but it doesn't - you'd be better off reading the documentation instead of making incorrect assumptions.)
I hope you see now: scanf() is hard to get right. It's evil. Why not input the whole line at once then parse it using sane functions?
char buf[LINE_MAX];
while (fgets(buf, sizeof buf, stdin) != NULL) {
int year = strtol(buf, NULL, 0);
const char *p = strchr(buf, ' ');
if (p != NULL) {
char name[LINE_MAX];
strcpy(name, p + 1); // safe because strlen(p) <= sizeof(name)
}
}

File write not correct

I'm writing some strings to a file using the following function...
void writeText(const char* desc){
FILE * pFile;
pFile = fopen ("CycleTestInfo.txt","a+");
fputs (desc,pFile);
fclose(pFile);
}
...inside of a for loop:
for(int i=0; i<numCycles; i++){
string cycle("---NEW CYCLE ");
cycle+=(char)i;
cycle+= "---\r\n";
writeText(cycle.c_str());
}
I have two issues though.i doesnt show up in my textfile and the newline does not appear for the first string written in my text file. For example, if numCycles is 4, I get the following output in my textfile.
---NEW CYCLE Cycle Done!
---NEW CYCLE ---
Cycle Done!
---NEW CYCLE ---
Cycle Done!
---NEW CYCLE ---
Cycle Done!
When I want it to look like this:
---NEW CYCLE 1---
Cycle Done!
....
i doesnt show up in my textfile
It's because you are writing character with ASCII value 1. Value of character '1' is different and can be easily retrieved by adding value of '0' to i like this: char c = '0' + i;
the newline does not appear for the first string written in my text file
First time i is equal to 0 which is also the value of the terminating character '\0'
Check out this article: C++ Character Constants
I doubt (char)i is the way to go there, you should try (char)((int)'0' + i)

Access Violation 00000000 when using Delete();

I am trying to delete every character from the beginning of my string, that is not an Alpha-character.
However, when there are only non-alpha characters (like "!!" or "?!?") in the string, it spits out an Access Violation!
Here is my code:
// The Log(); is a routine that adds stuff to my log memo.
Log('Begin Parse');
while not IsLetter(ParsedName[1]) do
begin
Log('Checking Length - Length is '+IntToStr(Length(ParsedName))+' ...');
if Length(ParsedName) <> 0 then
Begin
Log('Deleting Char ...');
Delete(ParsedName,1,1);
Log('Deleted Char ...');
End;
Log('Checking Length - Length is now '+IntToStr(Length(ParsedName))+' ...');
end;
// It never reaches this point!
Log('End Parse');
This is what my log produces:
21:51:19: Checking Length - Length is 2 ...
21:51:19: Deleting Char ...
21:51:19: Deleted Char ...
21:51:19: Checking Length - Length is now 1 ...
21:51:19: Checking Length - Length is 1 ...
21:51:19: Deleting Char ...
21:51:19: Deleted Char ...
21:51:19: Checking Length - Length is now 0 ...
21:51:19: Access violation at address 007A1C09 in module 'Project1.exe'. Read of address 00000000
As you see, it happens right after all the chars have been deleted. I assume the problem lies that somehow, I am trying to access something that is not there, but how I am doing that, I cannot see.
EDIT: Yes, I know it's a stupid question and all that stuff - I just oversaw something. Don't tell me that doesen't ever happen to you ;)
This question has nothing to do with Delete. Delete works even if you tell it to delete characters that do not exist.
The line
while not IsLetter(ParsedName[1]) do
tries to access ParsedName[1], so this character has better to exist. Your code isn't particularly beautiful, but a simple workaround is
while (length(ParsedName) > 0) and not IsLetter(ParsedName[1]) do
You can do just
while (length(ParsedName) > 0) and not IsLetter(ParsedName[1]) do
Delete(ParsedName, 1, 1);
You will want to also add in a check that the length of the string is > 0 in the While test.
You are checking to see if it is numeric before your if statement to check the length of the string. Alternately you could move your check of the string length to After where you remove the character. However ya want to do it :)

Resources