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 :)
Related
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.
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.
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)
}
}
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)
I've got this
WCHAR fileName[1];
as a returned value from a function (it's a sys 32 function so I am not able to change the returned type). I need to make fileName to be null terminated so I am trying to append '\0' to it, but nothing seems to work.
Once I get a null terminated WCHAR I will need to pass it to another sys 32 function so I need it to stay as WCHAR.
Could anyone give me any suggestion please?
================================================
Thanks a lot for all your help. Looks like my problem has to do with more than missing a null terminated string.
//This works:
WCHAR szPath1[50] = L"\\Invalid2.txt.txt";
dwResult = FbwfCommitFile(szDrive, pPath1); //Successful
//This does not:
std::wstring l_fn(L"\\");
//Because Cache_detail->fileName is \Invalid2.txt.txt and I need two
l_fn.append(Cache_detail->fileName);
l_fn += L""; //To ensure null terminated
fprintf(output, "l_fn.c_str: %ls\n", l_fn.c_str()); //Prints "\\Invalid2.txt.txt"
iCommitErr = FbwfCommitFile(L"C:", (WCHAR*)l_fn.c_str()); //Unsuccessful
//Then when I do a comparison on these two they are unequal.
int iCompareResult = l_fn.compare(pPath1); // returns -1
So I need to figure out how these two ended up to be different.
Thanks a lot!
Since you mentioned fbwffindfirst/fbwffindnext in a comment, you're talking about the file name returned in FbwfCacheDetail. So from the fileNameLength field you know length for the fileName in bytes. The length of fileName in WCHAR's is fileNameLength/sizeof(WCHAR). So the simple answer is that you can set
fileName[fileNameLength/sizeof(WCHAR)+1] = L'\0'
Now this is important you need to make sure that the buffer you send for the cacheDetail parameter into fbwffindfirst/fbwffindnext is sizeof(WCHAR) bytes larger than you need, the above code snippet may run outside the bounds of your array. So for the size parameter of fbwffindfirst/fbwffindnext pass in the buffer size - sizeof(WCHAR).
For example this:
// *** Caution: This example has no error checking, nor has it been compiled ***
ULONG error;
ULONG size;
FbwfCacheDetail *cacheDetail;
// Make an intial call to find how big of a buffer we need
size = 0;
error = FbwfFindFirst(volume, NULL, &size);
if (error == ERROR_MORE_DATA) {
// Allocate more than we need
cacheDetail = (FbwfCacheDetail*)malloc(size + sizeof(WCHAR));
// Don't tell this call about the bytes we allocated for the null
error = FbwfFindFirstFile(volume, cacheDetail, &size);
cacheDetail->fileName[cacheDetail->fileNameLength/sizeof(WCHAR)+1] = L"\0";
// ... Use fileName as a null terminated string ...
// Have to free what we allocate
free(cacheDetail);
}
Of course you'll have to change a good bit to fit in with your code (plus you'll have to call fbwffindnext as well)
If you are interested in why the FbwfCacheDetail struct ends with a WCHAR[1] field, see this blog post. It's a pretty common pattern in the Windows API.
Use L'\0', not '\0'.
As each character of a WCHAR is 16-bit in size, you should perhaps append \0\0 to it, but I'm not sure if this works. By the way, WCHAR fileName[1]; is creating a WCHAR of length 1, perhaps you want something like WCHAR fileName[1024]; instead.
WCHAR fileName[1]; is an array of 1 character, so if null terminated it will contain only the null terminator L'\0'.
Which API function are you calling?
Edited
The fileName member in FbwfCacheDetail is only 1 character which is a common technique used when the length of the array is unknown and the member is the last member in a structure. As you have likely already noticed if your allocated buffer is is only sizeof (FbwfCacheDetail) long then FbwfFindFirst returns ERROR_NOT_ENOUGH_MEMORY.
So if I understand, what you desire to do it output the non NULL terminated filename using fprintf. This can be done as follows
fprintf (outputfile, L"%.*ls", cacheDetail.fileNameLength, cacheDetail.fileName);
This will print only the first fileNameLength characters of fileName.
An alternative approach would be to append a NULL terminator to the end of fileName. First you'll need to ensure that the buffer is long enough which can be done by subtracting sizeof (WCHAR) from the size argument you pass to FbwfFindFirst. So if you allocate a buffer of 1000 bytes, you'll pass 998 to FbwfFindFirst, reserving the last two bytes in the buffer for your own use. Then to add the NULL terminator and output the file name use
cacheDetail.fileName[cacheDetail.fileNameLength] = L'\0';
fprintf (outputfile, L"%ls", cacheDetail.fileName);