1

today i was trying to get friendly with char * string... but it seems im failing :) Every time i call strcmp/strncmp/strcpy function my source gets corrupted...

here is the snippet

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

struct student
{
    int UID;
    char name[20];
    char surname[20];
};

char * getString(int minChars, int maxChars);

struct student * myStud;

int main(int argc, char** argv) {

    myStud = (struct student*)malloc(sizeof(struct student));
    while(1)
    {
        printf("\nEnter new name: ");
        strcpy(myStud->name,getString(1,19));
        printf("\n The values is now %s",myStud->name);
    }
    return (EXIT_SUCCESS);
}

char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];
scanAgain:
    scanf("%s",&string);
    if(strlen(string)<minChars)
    {
        printf("\nToo few symbols, try again: ");
        goto scanAgain;
    }
    if(strlen(string)>maxChars)
    {
        printf("\nToo many symbols, try again: ");
        goto scanAgain;
    }
    string[maxChars]='\0';
    return(string);
}

Output:

Enter new name: Alekasdasd

 The values is now Alekasda�#
Enter new name: 

im just a beginner so it might be something very simple... might be not. oh and by the way, using linux and netbeans as SDK, gcc as compiler.

Alex
  • 13
  • 3

4 Answers4

3

You're returning a pointer to a stack variable.

char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];

When getString returns, string is invalid. Your return value points to this invalid string.

Use:

char * getString(int minChars, int maxChars, char * string) {

    return string;
}
...
char string[100];
getString(1, 2, string);

Also, goto? Stop that please - use for, while do, do while but not goto

Erik
  • 88,732
  • 13
  • 198
  • 189
  • yeah, i know about goto, ill change that :)) – Alex Mar 12 '11 at 23:47
  • Erik has a great point about a means of not relying on a hidden buffer, which can lead to defects in the code. – Heath Hunnicutt Mar 13 '11 at 00:35
  • Don't _blindly_ believe that `goto` is bad, understand _why_ that's thought to be the case. It's only bad because it can lead to less readable code. There are (very limited) situations where it's fine to use (not _this_ particular case since you can achieve the same end with more structured loops). – paxdiablo Mar 13 '11 at 00:40
2
char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];
    ...
    return(string);
}

The "string" array here is only allocated for the scope of the getString() function. Once it returns (goes out of scope), it ceases to exist and will be overwritten by the rest of your program. The "return(string)" statement returns the pointer of this data that's not allocated anymore -- not the data itself. This happens due to the implicit array-to-pointer conversion in C.

Instead of doing this, your getString() function should take a char* as an argument, which is allocated in the calling function.

intgr
  • 19,834
  • 5
  • 59
  • 69
  • thanks, i just wrote this get string thingy because got annoyet by segmentation faults when using scanf(), also automatic scanf "reading" immediately after printf()... – Alex Mar 13 '11 at 00:07
1

I see two problems with your getString() function:

  1. The string variable must be declared static so that the memory used for it is not released (stack, popped) when the function returns.
  2. The parameter to scanf() you do not want the & token, but simply the pointer to the buffer, string.

That is, change the lines:

char string[maxChars+1];
scanf("%s",&string);

to read

static char string[maxChars+1];
scanf("%s",string);

The reason you do not want the ampersand in the scanf() call is the following from the man page, man 3 scanf:

      s      Matches a  sequence  of  non-white-space  characters;  the  next
              pointer must be a **pointer to character array** that is long enough
              to hold the input sequence and the  terminating  null  character
              ('\0'), which is added automatically.  The input string stops at
              white space or at the  maximum  field  width,  whichever  occurs
              first.
Heath Hunnicutt
  • 18,667
  • 3
  • 39
  • 62
  • 1
    static isn't really a good solution - it produces such hard to find problems when he e.g. calls `foo(getString(), getString())` – Erik Mar 12 '11 at 23:38
  • Only programmers produce calls. Therefore it is most important that C programmers understand `static`. The OP writes that he is learning today. My conclusion is that he's better off experimenting with static, also fixing his pointer usage, and learning, than worrying about a problem he doesn't currently have. Funny that static, the word, use to mean, in stasis, and has come to mean, sparky noise. Will he someday run in to the problem you describe? What will happen that day? – Heath Hunnicutt Mar 12 '11 at 23:42
  • static is useful. But IMO it's wrong for this function. Also, `&string` and `string` are equivalent in this context - using just `string` makes the source prettier though. – Erik Mar 12 '11 at 23:45
0

240 lines is not a "snippet". As James suggested in his comment, reduce the code to the minimum number of lines needed to reproduce the problem. At that stage the cause of the problem should become obvious to you -- if not try posting again.

2.718
  • 435
  • 2
  • 9
  • 2
    0: -1 for not an answer; +1 for a **very good suggestion**. That makes it 0 in total :) – pmg Mar 12 '11 at 23:48