Pointer to a string - C - c

I am parsing a text file, and when I come across the word .word, I want to grab the rest of the line. Here is what I have so far:
char *word_ptr;
if (strstr(token, ":")){
// Some code
}
else if ((word_ptr = strstr(token, ".word"))) {
char *string_wanted = word_ptr + 6;
printf("Rest: '%s'\n", string_wanted);
}
string_wanted is not printing correctly. Is my usage of word_ptr correct when assigning it in the else-if statement? string_wanted is printing out nothing. When I add a 7 instead of a 6, it prints out 'ize'. I had the word size in my text file but now I removed it, I deleted the file and re-created it and done a clean build and the word 'ize' still shows up!! It does not exist in the file at all anymore so where did it come from?? I am really frustrated the word 'size' does not exist anymore in the file.
Here is what the file looked (when I had the word 'ize'):
array: .word 0:10
array_size: .word 10
Now I just removed the second line, so it is:
array: .word 0:10
Why isn't word_ptr printing out 0:10 when I add a 6 to it? I am pretty sure that word_ptr points to .word because when I print it, it prints .word. When tokenizing the line, array: is being tokenized so I know that it is getting there.
Any suggestions?
Thanks for your help.

We're running around in circles a bit here. I think I see where your confusion is now, so I'll try to lay it out. Your tokenizer is taking a string and breaking it up into tokens. Each of these tokens is a separate string by itself. You don't specify what characters you are tokenizing on, so I'll just assume the space character.
In this case the string:
array: .word 0:10
becomes three new strings:
"array:"
".word"
"0:10"
If you are looping on your tokens (it appears that you are) then first time through the loop token will be "array:", the second time it will be ".word" and the third time it will be "0:10".
This evaluation:
word_ptr = strstr(token, ".word")
will only find ".word" during the iteration in which token contains ".word". When you then increment word_ptr by 6 chars you have moved past the end of token into undefined memory. Yes, "0:10" appears two characters after ".word" in your original string, but we are not looking at the original string in your call to strstr. We are looking just at token and token only contains ".word".
This is why it's failing. How to fix it depends somewhat on the rest of your implementation.

When you set *string_wanted to word_ptr + 6, you are pointing string_wanted at the null that terminates the string. So when you try to print *string_wanted you get an empty string. Try getting the next token instead.

Wouldn't your if (strstr(token, ":")) be true for all of your strings? It wouldn't ever get to the block of code you're asking about.

Related

I need to print out all of the words in the file that begin with an uppercase character

i need to access a file and from that file i need to print out all the words that starts with a capital letter and also how many times the words have occurred. for example in the file there is a text "the Program should Display Files and also Files"
now the output should be:
Text
Program
Display
Files(2)//This word is written two times
enter image description here
while (!feof(..)) is normally not a good idea, instead write
while (fgets(readLine,sizeof(readLine), fpointer) != NULL)
{
}
it seems ptr is superfluous in this context, if you want to check for words in the line you should move it forward in the line?
alt. use instead the runtime function strtok:
for (ptr = strtok(readLine, " "); ptr != NULL; ptr = strtok(NULL, " ")
{
// now ptr will point to each word in the line, then you just check
// if the first character is upper case.
}
This sounds like a homework assignment, so I am not going to put the code here. I can give you the steps to take to have a general idea:
Open and read the file
Use something like strtok to split the lines into words
Loop over the words and check the first character (remember that a word is an array of chars. You can check if it's in range of 60 - 95 as based on the ascii table.
To count words you can create a hashmap in which you store the word with a count as value e.g. {word1: 1, word2: 2}
In the end you go over all the keys in the hashmap and print the key + count.

Indexing in fread(): Is there a way to set the minimum index to be returned?

Context:
I am trying to read a file, and find out what character is where in the section that I am reading. For the grand scheme of this part of the program, I am using pthreads and fread().
Right now, my code looks like this:
excess=( fread( thread_data[i].buffer, 1, 30, f ) );
printf("\n\nSegFault 1 \n\n%s\n\n\n", thread_data[i].buffer);
printf("\n\nSegFault 2 n\n%s\n\n\n", &thread_data[i].buffer[10]);
To put everything into context, the first statement is printing the entire buffer, including leftover garbage is I am not setting up a null-terminator quite yet.
Then, we I call the second printf, I am getting everything from the 10th character in buffer to the last character of buffer. For example:
frist printf: 1234567890 abcdefgh
second printf: abcdefgh
Question:
How do I index buffer such that I can retrieve a single character to play with? If we look at the above example, when I call:
&thread_data[i].buffer[10]
I am expecting to return ' ', that is, a space
You have the indexing mostly right, but the printing wrong. You can reference the char at index 10 in the buffer like so:
thread_data[i].buffer[10]
If you instead take the address of that char, the resulting char * can be used to refer to the C string consisting of the tail of thread_data[i].buffer starting at index 10. So try this:
printf("\n\nSegFault 2 n\n%c\n\n\n", thread_data[i].buffer[10]);
Note the small changes both to the format string and to the argument.

C language, char=char with unexpected results

Hi everybody and thanks in advance for any help, this is the situation:
#define N 12
[..]
char vect[N][2];
char strng[2];
[..]
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][2]=strng[0];
Now, if in string[2] I have "c 2", what I expect in vect[i][0] is '2' and in vect[i][1] 'c'.
I use code::blocks and watching vect I have instead "2#", but it could be "2À" as well.
Can you help me? Where am I wrong?
Array indexes goes from zero up to the size minus one. So using e.g. strng[2] you access the third entry in the two-entry array. Accessing an array out of bounds leads to undefined behavior and the data will be indeterminate.
You should also remember that all strings in C are one more character than reported by e.g. strlen, and that extra character is a special terminator character. So if you want a two-character string, you really need three characters: Two for the string, and one for the terminator.
Rewrite these statements
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][2]=strng[0];
the following way
vect[i][0]=strng[1]; //this two lines are in a simple for cycle
vect[i][1]=strng[0];
provided that string contains two characters { 'c', '2' }.
Take into account that array string can not have string literal "c 2", because you defined it as
char strng[2];
that is it can contain only two characters.
If you want that the array would contain indeed "c 2" then you have to define it either as
char strng[3];
or as
char strng[4];
if you want to include the terminating zero.
In this case you may write
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][1]=strng[0];
Assuming strng literally contains "c 2", then your memory is the issue. strng[2] contains 3 cells iirc. 2 for holding chars and then a null terminator (ie \0). so when you try to access strng[2], (which you cant because you can only go to N-1 cells, where N is the number allocated for it) it contains undefined results, since it isnt null terminated and you are reaching beyond memory you allocated

read from text file and put into struct

i have assembler file actually text file like that
1 # Test case 1 for assembler
2
3 .text
4 test1: lwa $1,val1
5 prh $1
6 val12: lwa $2,val2
7 prh $2
..................
i am reading each line with fgets and keeping in char buffer which name is "linebuffer"
and im reading linebuffer with sscanf.
while((fgets(linebuffer,sizeof(linebuffer),ifp)!=NULL)
{
sscanf(linebuffer,"%s%s%s%s",line[i].label,line[i].opcode,line[i].operands,line[i].comment);
......
}
and i want keep them into struct,
struct instrucion{
char lable[8];
char opcode[4];
char opearand[15];
char comment[100];
}line[65536];
problem is some columns doesnt have anything just space and sscanf skipping spaces and reading very next string and keeping in first column. sorry i could not understand exactly but i hope somebody is understand.
for example i want like that for 3rd line;
line[2].label=NULL
line[2].opcode=".text"
line[2].opernds=NULL
line[2].comment=NULL
for 4th line;
line[3].label="test1:"
line[3].opcode="lwa"
line[3].operands="$1,val1"
line[3].comment=NULL
problem is starting with 5th line its has to be like that
line[4].label=NULL
line[4].opcode="prh"
line[4].operands="$1"
line[4].comment=NULL
buts when i run code im getting this result;
line[4].label="prh"
line[4].opcode="$1"
line[4].opernds=NULL
line[4].comment=NULL
how can i deliminate this linebuffer correctly?
OK, so your first problem is that fgets() does not read one line - It reads up to sizeof(linebuffer) number of bytes, you can see it's man page here:
http://linux.die.net/man/3/gets
Second, say that you do have only one line in the string "linebuffer", what you would like to do is use sscanf return value to determine which tokens appear in the line (scanf functions family return the number of parameters that were read from the stream).
Third, pay attention to the fact the scanf considers only spaces and newlines as tokens separators, so it will not separate the string "$1,val1" to the two sub-strings - you will need to do it manually.
And finally, there's a string-parsing function that can maybe make you life easier- strtok_r. You can see it's man page here:
http://linux.die.net/man/3/strtok_r
Amnon.

Remove redundant whitespace from string (in-place)

Ok so i posted earlier about trying to (without any prebuilt functions) remove additional spaces so
"this is <insert many spaces!> a test" would return
"this is a test"
Remove spaces from a string, but not at the beginning or end
As it was homework i asked for no full solutions and some kind people provided me with the following
"If you need to do it in place, then create two pointers. One pointing to the character being read and one to the character being copied. When you meet an extra space, then adapt the 'write' pointer to point to the next non space character. Copy to the read position the character pointed by the write character. Then advance the read and write pointers to the character after the character being copied."
The problem is i now want to fully smash my computer in to pieces as i am sooooo irritated by it. I didnt realise at the time i couldnt utilise the char array so was using array indexes to do it, i thought i could suss how to get it to work but now i am just using pointers i am finding it very hard. I really need some help, not full solutions. So far this is what i am doing;
1)create a pointer called write, so i no where to write to
2)create a pointer called read so i no where to read from
(both of these pointers will now point to the first element of the char array)
while (read != '\0')
if read == a space
add one to read
if read equals a space now
add one to write
while read != a space {
set write to = read
}
add one to both read and write
else
add one to read and write
write = read
Try just doing this yourself character by character on a piece of paper and work out what it is you are doing first, then translate that into code.
If you are still having trouble, try doing something simpler first, for example just copying a string character for character without worrying about the "remove duplicate spaces" part of it - just to make sure that you haven't made a silly mistake elsewhere.
The advice of trying to do it with pen and paper first is good. And it really doesn't matter if you do it with pointers or array indexing; you can either use a reader and a writer pointer, or a reader and a writer index.
Think about when you want to move the indices forward. You always move the write index forward after you write a character. You move the read index forward when you've read a character.
Perhaps you could start with some code that just moves over the string, but actually doesn't change it. And then you add the logic that skips additional spaces.
char p[] = "this is a test";
char *readptr = &p[0];
char *writeptr = &p[0];
int inspaces = 0;
while(*readptr) {
if(isspace(*readptr)) {
inspaces ++;
} else {
inspaces = 0;
}
if(inspaces <= 1) {
*writeptr = *readptr;
writeptr++;
}
readptr++;
}
*writeptr = 0;
Here's a solution that only has a single loop (no inner loop to skip spaces) and no state data:
dm9pZCBTdHJpcFNwYWNlcyAoY2hhciAqdGV4dCkNCnsNCiAgY2hhciAqc3JjID0gdGV4dCwgKmRl
c3QgPSB0ZXh0Ow0KICB3aGlsZSAoKnNyYykNCiAgew0KICAgICpkZXN0ID0gKihzcmMrKyk7DQog
ICAgaWYgKCpzcmMgIT0gJyAnIHx8ICpkZXN0ICE9ICcgJykNCiAgICB7DQogICAgICArK2Rlc3Q7
DQogICAgfQ0KICB9DQogICpkZXN0ID0gMDsNCn0NCg==
The above is Base64 encoded as this is a homework question. To decode, copy the above block and paste into this website to decode it (you'll need to check the "Decode" radio button).
assuming you're trying to write a function like:
void removeSpaces(char * str){
/* ... stuff that changes the contents of str[] */
}
You want to scan the string for consecutive spaces, so that your write pointer is always trailing your read pointer. Advance your read pointer to a place where you are pointing at a space, but the next character is not a space. If your read and write pointers are not the same, then your write pointer ought to be pointing at the beginning of a sequence of spaces. The difference between your write and read pointer (i.e. read_pointer - write_pointer) will tell you the number of consecutive spaces that need to be overwritten to close the gap. When there is a difference of greater than zero, (prefix) advance both pointers along by that many positions, copying characters as you go. When you're read pointer is at the end of the string ('\0'), you should be done.
Can you use regular expressions? If so, it might be really easy. Use a regex to replace \s{2,}? with a single space. The \s means any white space (tabs, spaces, carriage feeds...); {2,} means 2 or more; ? means non-greedy. (Disclaimer: my regex might not be the best one you could write, since I'm no regex pro. Also, it's .net syntax, so the regex library for C might have slightly different syntax.)
Why don't you do something like this:
make a second char** that is the same length as the first. As you run through the first array with your pointers keep an extra pointer on the last space you've seen. If the last space you saw was the previous element then you don't copy that char to the second array.
But I would start with something that runs through the char** by each character and prints out each char. If you can make that happen then you can work on actually copying them into a second char**.

Resources