-2

I'm working on an assignment that is supposed to parse a string into separate tokens without the use of the c string library and while dynamically allocating any necessary memory. I thought I had everything working correctly, except now it looks like every value is being overwritten every time I write a new value.

Here's my code. Sorry it's a mess, I've been in a hurry and reluctantly have been working with functions I don't fully understand. The problem is probably something dumb, but I'm out of time and it's clear I probably wont be able to figure it out myself.

int makearg(char s[], char **args[]);

int main() {    char **tokenArray;    char strInput[MAXSTRING];    int tokenResult;    int i = 0;

   printf("Input String to be Parsed: ");    scanf("%[^\n]%*c", strInput);

   tokenResult = makearg(strInput, &tokenArray);

   printf("argc: %d\n", tokenResult);    for (i = 0; i < tokenResult; i++)    {
      printf("arg(%d): %s\n", i, tokenArray[i]);    } }

int makearg(char s[], char **args[]) {    int numTokens = 0;    int lastSpace = 0;    int i;    int fakeI;    char token[MAXSTRING];       int subFromPos = 0;    int firstToken = 1;

   *args = NULL;    while ((s[i] != '\n') && (s[i] != '\0') && (s[i] != '\r'))    {
      fakeI = i;

      if ((s[i + 1] == '\n') || (s[i + 1] == '\0'))
      {
         fakeI = i + 1;
      }

      token[i - lastSpace - subFromPos] = s[i];

      if ((s[fakeI] == ' ') || (s[fakeI] == '\n') || (s[fakeI] == '\0') || (s[fakeI] == '\r'))
      {
         if (firstToken == 1)
         {
            token[fakeI - lastSpace] = '\0';
            firstToken = 0;
         } else if (firstToken == 0){
            token[i - lastSpace] = '\0';
            printf("Saved Token 1: %s\n", *args[numTokens - 1]); //test to see if the token got written properly
            if (numTokens > 1){
               printf("Prior Saved Token: %s\n", *args[numTokens - 2]); //test to see if the tokens are overwritten
            }
            if (numTokens > 2){
               printf("Prior Saved Token 2: %s\n", *args[numTokens - 3]); //test to see if the tokens are overwritten
            }
         }
         *args = realloc(*args, (numTokens + 1));
         args[numTokens] = NULL;
         args[numTokens] = realloc(args[numTokens], (fakeI - lastSpace + 1));
         *args[numTokens] = token;
         printf("Saved Token: %s\n", *args[numTokens]); //test to see if the token got written properly
         numTokens++;
         lastSpace = fakeI;
         subFromPos = 1;
      }
      i++;    }    numTokens++;    return numTokens; }

For whatever reason Saved Token, Saved Token 1, Prior Saved Token, and Prior Saved Token 2 all print the same value every time they run (by which I mean if one of them prints the word "hello", they all print the word hello. That seems to tell me that the previous data is being overwritten.

Additionally, the for-loop in the main function is supposed to go through and print every value in the array, but instead it's only printing the following (in this scenario I was testing with the string "hello my one true friend":

arg(0): friend

arg(1): (null)

arg(2): (null)

What am I doing wrong here? I'm sure it's something dumb that I'm overlooking, but I just can't find it. Am I writing in the data incorrectly? Is it actually not being overwritten and just being printed incorrectly. At this point any advice at all would be greatly appreciated.

  • Step through it using a debugger. – Cheatah Feb 23 '22 at 01:08
  • 2
    @Cheatah sadly that never happens – pm100 Feb 23 '22 at 01:12
  • It looks like you're copying data in the local variable `token` then assigning pointers in the array to point to it. So, they all point to the same place, and if the data stored there changes they all point to that new data. When the function returns all the pointers are dangling because the local variable they point to no longer exists. Use `strcpy` to copy the data into memory you allocate. – Retired Ninja Feb 23 '22 at 01:18
  • 1
    Edit the question to provide a [mre]. – Eric Postpischil Feb 23 '22 at 01:21
  • @RetiredNinja We arent allowed to use strcopy for this assignment. Is there another way to accomplish the same thing? – Ian Finnigan Feb 23 '22 at 01:22
  • `scanf("%[^\n]%*c", strInput);` is worse than [`gets()`](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) as it lacks a width limit. Don't use `scanf()`. Use `fgets()` instead. – chux - Reinstate Monica Feb 23 '22 at 01:25
  • @IanFinnigan You could write a replacement `strcpy` function. It's pretty simple, just copy character by character until you reach the end of the source string. Guess you didn't like the code formatting. What you reverted to is dreadful to read. – Retired Ninja Feb 23 '22 at 01:27
  • Without a [mcve], there is little that can be done. – chux - Reinstate Monica Feb 23 '22 at 01:31
  • @chux-ReinstateMonica this code compiles fine, its trivial to debug it, fixing not so much – pm100 Feb 23 '22 at 01:38
  • @RetiredNinja Okay, I tried doing that with a for-loop incrementing int j until token[j] = '\0', with the loop running the line 'args[numTokens][j] = token[j];' but now the test prints only return the first letter of each word (I also removed the '*' from the front of each of those print statements because with it there they now cause segmentation faults) and the for-loop inside of main doesn't print anything. Any idea why this is happening? – Ian Finnigan Feb 23 '22 at 02:17

1 Answers1

0

Ok well my dev env picked up immediatly

int i;  <<<<=====
int fakeI;
char token[255];
int subFromPos = 0;
int firstToken = 1;

*args = NULL;
while ((s[i] != '\n') && (s[i] != '\0') && (s[i] != '\r')) { <<<<<=

gave

C4700   uninitialized local variable 'i' used

after that all bets are off

pm100
  • 48,078
  • 23
  • 82
  • 145