Home > Software design >  Function for scanning string - what's the problem?
Function for scanning string - what's the problem?

Time:12-21

char* scanString()
{
    char* str = NULL;
    char* temp = NULL;
    int  numOfChars = 0;
    char c = '0';
    while (c != '\n')
    {
        scanf(" %c", &c);
        if (c != '\n')
        {
            if (numOfChars == 0)
            {
                char* str = (char*)malloc(sizeof(char));
                char* temp = str;
                if (str == NULL)
                    return str;
                str[0] = c;
                numOfChars  ;
            }
            else
            {
                str = (char*)realloc(str, sizeof(char) * (numOfChars   1));
                str[numOfChars] = c;
                if (str == NULL)
                    return temp;
                else
                {
                    temp = str;
                    numOfChars  ;
                }
            }
        }
    }
    str = (char*)realloc(str, sizeof(char) * (numOfChars 1));
    if (str == NULL)
    {
        str = temp;
        return str;
    }
    str[numOfChars] = '\0';
    return str;
}
int main()
{
    char* m;
    printf("write:\n");
    m = scanString();
    printf("%s\n", m);
}

I tried to create a function for scanning a string of unknown size char by char and i don't know what'ss the problem here. Btw please don't approach me to any other code or try to use different libraries.

CodePudding user response:

There is one big error and some inconsistencies.

The big error is here:

        if (numOfChars == 0)
        {
            char* str = (char*)malloc(sizeof(char)); // Oops a new var!
            char* temp = str;                        // and another one!
            if (str == NULL)
                return str;
            str[0] = c;
            numOfChars  ;
        }

You declare 2 new variables in that bloc that will hide the variables of outer scope. As a result, the first character will be lost and you will get a random value.

The inconsistencies:

  • tmp is useless and should be removed

  • you read with a format " %c". The format will skip any blank character including \n. It should be "%c"

  • you fail to test the return value of scanf. On end of file (of any other read error) you will enter an endless loop. It should be:

          if (1 != scanf("%c", &c)) break;
    

Once this is fixed, you should get the expected output, but other improvements are still possible:

  • the idiomatic way to read one character is getc or getchar
  • allocating one character at a time is an anti-pattern because (re-)allocation is a rather expensive operation. For a realloc world program, you should always allocate a bunch or memory and keep track of the available part
  • sizeof(char) is 1 per standard
  • the distinction for numOfChars == 0 is useless. realloc on a NULL pointer is the same of malloc.

CodePudding user response:

Your code is overly complicated and wrong and as stated in a comment you need to replace the format string " %c" with "%c".

The main problem is here:

if (numOfChars == 0)
{
  char* str = (char*)malloc(sizeof(char));

You declare a new str variable which shadows the str variable you've declared at the beginning of the function.

Just replace char* str = (char*)malloc(sizeof(char)) with str = malloc(sizeof(char));. BTW the cast is not necessary.

You have the same problem with temp.

The code below is entirely based on your code, but it is simpler and correct. Basically the case where numOfChars is 0 should not be treated specially. You can just use realloc, because realloc(NULL, foo) is equivalent to malloc(foo) .

char* scanString()
{
  char* str = NULL;
  char* temp = NULL;
  int  numOfChars = 0;
  char c = '0';
  while (c != '\n')
  {
    scanf("%c", &c);
    if (c != '\n')
    {
      str = realloc(str, sizeof(char) * (numOfChars   1));
      if (str == NULL)
        return temp;
      
      str[numOfChars] = c;
      temp = str;
      numOfChars  ;
    }
  }
   
  str = realloc(str, sizeof(char) * (numOfChars   1));
  if (str == NULL)
  {
    str = temp;
    return str;
  }
  str[numOfChars] = '\0';
  return str;
}

Or even simpler:

char* scanString()
{
  char* str = NULL;
  char* temp = NULL;
  int  numOfChars = 0;
  char c = '0';
  while (c != '\n')
  {
    scanf("%c", &c);

    str = realloc(str, sizeof(char) * (numOfChars   1));
    if (str == NULL)
      return temp;

    str[numOfChars] = c;
    temp = str;

    if (c == '\n')
    {
      str[numOfChars] = '\0';
    }

    numOfChars  ;
  }

  return str;
}
  • Related