0

I am in the process of teaching myself C. I have the following code that prints a string char by char forwards and backwards:

#include<stdio.h>
#include<string.h>

main(){
    char *str; 
    fgets(str, 100, stdin);
    //printf("%i", strlen(str));
    int i;

    for(i = 0; i < strlen(str) - 1; i++){
        printf("%c", str[i]);
    }
    for(i = strlen(str); i > -1; i--){
        printf("%c", str[i]);
    }
}

When run, it gives me the following output (assuming I typed "hello"):

cello
ollec

In addition, if I uncomment the 7th line of code, I get the following output (assuming I typed "hello"):

6 ♠

For the life of me, I cannot figure out what I am doing that is causing the first character in the output to change. In the second example, I know that the string length would be 6 because 'h' + 'e' + 'l' + 'l' + 'o' + '\0' = 6. That is fine, but where is the spade symbol coming from? Why is it only printing one of them?

It is pretty obvious to me that I have some kind of fundamental misunderstanding of what is happening under the hood here and I cant find any examples of this elsewhere. Can anyone explain what is going wrong here?

Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
mstagg
  • 507
  • 4
  • 16
  • C isn't a good language to learn by trial-and-error because you don't know if you're seeing guaranteed results or [undefined behaviour](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior). It would save you a lot of time to [get a book](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). – M.M Feb 27 '15 at 23:02
  • A point that no answer has addressed yet is that `strlen` for input `hello` gives `6` not because it counts `\0` in the string. It is because `\n` is there before `\0` in string when the string is read by `fgets`. – haccks Feb 27 '15 at 23:04

5 Answers5

5

You never allocate memory for the string. Instead of

char *str;

use

char str[100];

so that you have enough space for the up to 100 characters you read in there with the fgets call.

Wintermute
  • 42,983
  • 5
  • 77
  • 80
  • This seems to be the appropriate answer (agreeing with what everyone else posted). Making the correction causes compile time errors concerning the wrong data types being passed to strlen() and fgets(). Mostly expecting *char but receiving **char. – mstagg Feb 27 '15 at 23:12
  • Edit: nvm, fixed it. Thanks! – mstagg Feb 27 '15 at 23:18
3

In this code:

char *str; 
fgets(str, 100, stdin);

str points to an effectively random location. Then you tell fgets to read characters and put them where str is pointing. This causes undefined behaviour; the symptoms you are seeing probably occur because str happened to point to some memory where the first character of that memory that was being used for other purposes, but the other characters weren't being used.

Instead you need to allocate memory:

char str[100];    // allocate 100 bytes
fgets(str, 100, stdin);

Pointers only point at memory which already is allocated somewhere; they do not "own" or "contain" any memory.

M.M
  • 138,810
  • 21
  • 208
  • 365
2

You should preallocate space for your string, otherwise you are writing to who knows where, which is bad.

char str[100]; //I must be big enough to hold anything fgets might pass me

You should also be sure to only access parts of the string which contain characters:

for(i = strlen(str)-1; i > -1; i--){
    printf("%c", str[i]);
}

Note that the character at strlen(str) is \0, the string-terminating null character. So you can access this space, but trying to print it or otherwise treating it like a standard letter is going to lead to issues at some point.

Richard
  • 56,349
  • 34
  • 180
  • 251
1

Your str is a pointer to char, but you don't have any actual character buffer for it to point to. You need a character array instead:

char str[100];

Only then can fgets have somewhere to store the data it reads.

Then on your reverse-printing loop, your indices are wrong:

for(i = strlen(str); i > -1; i--){

With the above, you try to print str[i] for i = strlen(str), but that's one past the end of the valid string data. Change to:

for(i = strlen(str) - 1; i > -1; i--){
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
0

The issue is that you are not allocating your

char *str

what you need to do is either

1)

char *str = malloc(sizeof(char) * 100);

and then when you are no longer using it:

free(str)

2)

char str[100];
  • `sizeof(char) == 1` by definition. – Iharob Al Asimi Feb 27 '15 at 23:00
  • I am aware of that, but the OP is just learning, and simply writing a malloc with a constant 100 inside may lead him to believe that it's the same situation for other types. –  Feb 27 '15 at 23:02