Stuck with C syntax - c

I am trying to remove spaces from the end of a char array (string).
This is the pseudo code of what I am doing, but it keeps deleting the whole string:
if(string length - 1 != a space)
return
Otherwise, it must equal a space, so
while *mypointer-- != a space
//This should loop back to where there is a character.
Outside of the while loop, I now add one to the pointer by doing
mypointer ++;
and then set mypointer '\0' to signal the end of the string.
I am doing something fundamentally wrong inside of my while, but I cannot seem to figure it out. What could it be?

A little clairvoyance:
while(*mypointer == a space) {
--mypointer;
}
mypointer[1] = '\0';
Notice that it is == a space not != a space.
Edit:
If I were going to write this, I'd probably really use something like:
#include <string.h>
...
char *mypointer = strrchr(string, ' ');
if (mypointer) *mypointer = '\0';

You're probably setting mypointer to \0, which sets the pointer to NULL. You need to set mypointer[1] to \0. Also, make sure you do the right thing for the following edge-cases:
when a string is all spaces,
when string length is 0.

Without the code we can just guess:
How is mypointer initialized?
Are you sure about the while loop condition? Should it be while 'last character is space'?

A slight improvement perhaps:
while(*mypointer == a space) {
*mypointer-- = '\0';
}

Have a look at this code that does the exact job to strip spaces from the end of the string...this is from the Snippets archive - it's an educational thing to watch what's going on when stepping through the debugger and very useful collection of C code also...

Related

Using getchar() to Read Two Strings

For the following code, I added two printf statements to test if the two strings are read properly. However, when I enter something like: abcabcabcza,cb
The outputs are:
abcabcabcza▒
cb9
Does anyone know where the symbol at the end of the first string, and the '9' at the end of the second string, come from? Thank you so much!
printf("\nEnter two words, seperated by a comma: ");
int temp1, temp2, index3, index4; char temp3[20], temp4[20];
index3=index4=0;
while((temp1 = getchar())!= ','){
temp3[index3++] = temp1;
}
printf("\n%s", temp3);
while((temp2 = getchar())!= '\n'){
temp4[index4++] = temp2;
}
printf("\n%s", temp4);
You need to add string terminators '\0' to your string before printing (or zero out the buffers memory first).
Also: you have declared buffers of size 20, but have no guards in your code to respect that allocated length, which means you could overrun them and corrupt memory. [Run with two words greater than 20 characters...]
'\n' and '\0' are different here. You need to add '\0' at the end of string because printf prints out string until it meets '\0'. C doesn't initializes array. If you do not initialize manually it will have garbage values.
I would do:
char temp3[20] = {0};
char temp4[20] = {0};
to fill out temp3 and temp3 with 0, which is same as '\0'.
when you give a string as 'abc' it will be saved as 'abc\0',so check for \0 also and dont print it
The string in C requires to be NULL-terminated.
A lot of functions use that terminator to announce the processor where the string ends.
What will hapan if not terminated? Lets get one simple string, with consumpption of 5 bytes of memory.
...[?][?][H][e][l][l][o][?][?][?]...
That causes a leak. As you see we haven't store a NULL. It causes u/b and you may get different signs on any new run. For us.. the processor puts the string in random blocks of memory. However gcc by default has optimizations to prevent that.

C - Array of strings (2D array) and memory allocation gets me unwanted characters

I have a tiny problem with my assignment. The whole program is about tree data structures but I do not have problems with that.
My problem is about some basic stuff: reading strings from user input and then storing them in an array list.
char str[1000];
fgets(str, 1000, stdin);
int x = 0;
int y = 0;
int z = 0;
char **list;
list = (char**)malloc((x+1)*sizeof(char));
list[x] = (char*)malloc((y+1)*sizeof(char));
while(str[z] != '\n')
{
list[x][y] = str[z];
z++;
if(str[z] == ',')
{
x++;
y = 0;
list = (char**)realloc(list, (x+1) * sizeof(char*));
list[x] = (char*)malloc((y + 1)*sizeof(char));
z++;
if(str[z] == ' ') // Skips space after the comma
{
z++;
}
}
else if(str[z] == '\n')
{
break;
}
else
{
y++;
list[x] = (char*)realloc(list[x], (y+1)*sizeof(char));
}
}
I pass this list array into another function.
As an example, inputs could be something like
Abcde, Fghijk, Lmnop, Qrstu
and I am trying to split each of these words into the array list.
Abcde
Fghijk
Lmnop
Qrstu
When I try to output the strings I sometimes get weird, excessive characters such as upside down question marks and numbers.
printf("%s ", list[some_number]);
gets me
Fghijk¿
or
Fghijk\200
All of my program works as expected except for this minor problem which I am having trouble solving. Even with the same exact inputs the bugs may or may not appear. I am guessing it has to do with memory allocation?
Thanks for your help!
You need to put '\0' at the end of your new string.
See most of the C library functions such as printf and strlen process strings assuming \0 as the end character of all. Otherwise, they keep on reading the memory out of bounds either making a memory violation or gets some where the value 0 and stops and all the bytes in between in the memory are interpreted to their extended ascii equivalent hence you are getting such a strange behaviour.
So, allocate an extra byte for \0 character and assign it to the last byte.
Either initialize your variables to null, or as tomato said, put a null character at the end of the new string.
C lacks many of the luxuries programmers now take for granted when it comes to memory management. You're on the right path with malloc but that function only allocates memory... it doesn't clear it out. As a result, your variables will have the correct amount of space (critical for reducing memory leaks and overflow errors), but will be filled with garbage. This garbage could be anything, and in your case, it's an upside down question mark. Appropriate, don't you think?
I could be mistaken since I can't run the code myself without more information, but after your
char **list;
list = (char**)malloc((x+1)*sizeof(char));
list[x] = (char*)malloc((y+1)*sizeof(char));
statements, you'll want to do something like this:
list = NULL;
and the like to clear out the garbage.
Furthermore, you may care to use the strlen() function (contained in string.h) to figure out just how many blocks of memory you need to allocate.
Clearing out the spaces you use for variables is a good practice to get into with C. Good to see you learning it as well.

C - reading past end of file with fgetc

I have the weirdest thing happening, and I'm not quite sure why it's happening. Basically what I need to do is use fgetc to get the contents of a simple ASCII file byte by byte. The weird part is it worked, but then I added a few more characters and all of a sudden it added a newline that wasn't there and read past the end of the file or something. Literally all I did was
do {
temp = (char*) checked_realloc (temp, n+1);
e = fgetc(get_next_byte_argument);
temp[n] = e;
if (e != EOF)
n++;
}
while (e != EOF);
And then to check I just printed each character out
temp_size = strlen(temp)-1;
for(debug_k = 0; debug_k < temp_size; debug_k++){
printf("%c", temp[debug_k]);
}
And it outputs everything correctly except it added an extra newline that wasn't in the file. Before that, I had
temp_size = strlen(temp);
But then it ended on some unknown byte (that printed gibberish). I tried strlen(temp)-2 just in case and it worked for that particular file, but then I added an extra "a" to the end and it broke again.
I'm honestly stumped. I have no idea why it's doing this.
EDIT: checked_realloc is just realloc but with a quick check to make sure I'm not out of memory. I realize this is not the most efficient way to do this, but I'm more worried about why I seem to be magically reading in extra bytes.
A safer way to write such operation is:
memset the memory bulk before use with zeros, if you are allocating memory prior to realloc.And every time you realloc, initialize it to zero.
If you are using a memory to access strings or use string functions on that memory always ensure you are terminating that memory with a NULL byte.
do{
temp = (char*) checked_realloc (temp, n+1);//I guess you are starting n with 0?
temp[n]=0;
e = fgetc(get_next_byte_argument);
temp[n] = e;
if (e != EOF)
n++;
} while (e != EOF);
temp[n]=0;
n=0;
I guess the above code change should fix your issue. You don't need strlen -1 anymore. :)
Cheers.
It sounds like you forgot to null terminate your string. Add temp[n] = 0; just after the while.

Reverse a string using recursion

I got this code from the internet but I couldnt get the whole code.
for example if(*str) . What does this code mean? and also can a string be returned? I thought that an array in main can be changed
directly in a function but here its been returned..
#include<stdio.h>
#define MAX 100
char* getReverse(char[]);
int main(){
char str[MAX],*rev;
printf("Enter any string: ");
scanf("%s",str);
rev = getReverse(str);
printf("Reversed string is: %s\n\n",rev);
return 0;
}
char* getReverse(char str[]){
static int i=0;
static char rev[MAX];
if(*str){
getReverse(str+1);
rev[i++] = *str;
}
return rev;
}
This is not the clearest example of recursion due to the use of the static variables. Hopefully the code generally seems clear to you, I suspect the part that is confusing to you is the same that was confusing to me at first.
if(*str){
getReverse(str+1);
rev[i++] = *str;
}
So line by line.
if(*str){
If we have not reached the null terminator.
getReverse(str+1);
Call the getReverse function on the next character of the string. It seems pretty straight forward up to here. But it also seems like it may not actually reverse anything because this is the next line
rev[i++] = *str;
We assign index i the character at the beginning of str and increment i but here is the tricky part. i may not be what you think. getReverse gets called before i is incremented. And i is static, so changes will persist between function calls. So, lets say we have a 5 letter word, let say "horse" we will end up with 6 calls on the stack to getReverse. The 6th will not do anything because that is where it finds the null terminator. The trick is that we will then go about resolving the calls in reverse order. First the call where str is pointing to 'e' will resolve and increment i because all the other ones are are still waiting for their calls to getReverse to return. So the last letters are actually the first ones to get added and increment i which is what can be confusing here.

Finding end of string: *s++ VS *s then s++

I'm writing a simple string concatenation program.
The program works the way I have posted it. However, I first wrote it using the following code to find the end of the string:
while (*s++)
;
However, that method didn't work. The strings I passed to it weren't copied correctly. Specifically, I tried to copy "abc" to a char[] variable that held "\0".
From reading the C K&R book, it looks like it should work. That compact form should take the following steps.
*s is compared with '\0'
s points to the next address
So why doesn't it work? I am compiling with gcc on Debian.
I found that this version does work:
strncat(char *s, const char *t, int n)
{
char *s_start = s;
while (*s)
s++;
for ( ; n > 0 && *t; n--, s++, t++)
*s = *t;
*(s++) = '\0';
return s_start;
}
Thanks in advance.
After the end of while (*s++);, s points to the character after the null terminator. Take that into account in the code that follows.
The problem is that
while (*s++)
;
Always Increments s, even when s is zero (*s is false)
while (*s)
s++;
only increments s when *s is nonzero
so the first one will leave s pointing to first character after the first \0, while the second one will leave s pointing to the first \0.
There is difference. In the first case, s will point to the position after '\0', while the second stops right at '\0'.
As John Knoeller said, at the end of the run it'll s will point to the location after the NULL. BUT There is no need to sacrifice performance for the correct solution.. Take a look for yourself:
while (*s++); --s;
Should do the trick.
In addition what has been said, note that in C it is technically illegal for a pointer to point to unallocated memory, even if you don't dereference it. So be sure to fix your program, even if it appears to work.

Resources