1

So I'm doing a few practice questions for a final exam coming up. and I'm having a lot of trouble with dynamic memory.

So the question wants to basically parse through 2 different sources and compare them to find the similar words. (one from a csv file and one from a cgi input)

so I figured I'd use malloc/calloc to put a string in each array slot and then compare each slot. but I'm having some issues with my code:

char buffer[100],buffer2[100],tmp[100],line[100];
char *token,*tok,*input;

int main()
{
char s[100]="search=cat+or+dog+store";
char *search=(char*)calloc(10,sizeof(char));

strcpy(buffer,s);
sscanf(buffer,"search=%s",buffer);
int k=0;
tok=strtok(buffer,"+");
   while(tok!=NULL)
   {
   strcpy(&search[k],tok);
    k++;
   tok=strtok(NULL,"+");
   }
printf("%d\n",k);
strcpy(&search[k],"\0");

***printf("%s",&search[0]);
   printf("%s",&search[1]);
   printf("%s",&search[2]);
   printf("%s",&search[3]);***

char* csv=(char*)calloc(10,sizeof(char));
char tmp2[100];

FILE *fp;
fp=fopen("web.csv","r");

  while(fgets(line,sizeof(line),fp)!=NULL)
  {
  strcpy(buffer2,line);
  token=strtok(buffer2,",");
      while(token!=NULL)
      {
      strcpy(csv,token);
      csv++;
      token=strtok(NULL,",");       
      } 
strcpy(csv,"\0");

free(csv);
free(search);
return(0);
}
  1. the part i put between * * i put in order to test if the strings were put inside the calloc. but nothing prints out or smt weird prints out. the same code was used for the latter bottom part and they are both either empty or only printing out weird fragmented part of the code.
  2. when i put the free(csv) and free(search), it says that "pointer being freed was not allocated". i looked it up but I can't seem to find a answer to why it does this?

thank you!

harekuin
  • 45
  • 1
  • 8
  • 1
    `sscanf(buffer,"search=%s",buffer);` ? Um... – WhozCraig Aug 11 '16 at 20:13
  • its to get rid of the "search="portion of the cgi string passed, which looks smt like this: seach=dog+or+cat+store. i dont need the search portion – harekuin Aug 11 '16 at 20:21
  • [How do I create an array of strings in C?](http://stackoverflow.com/questions/1088622/how-do-i-create-an-array-of-strings-in-c) – 001 Aug 11 '16 at 20:26
  • why *search inside of the sizeof? i thought it was only the 'type' that goes in there. also i tried it and it did smt? but :( doesnt make any sense either. the last tokenized word gets mixed into it all n the rest of it looks jumbled and broken characters. – harekuin Aug 11 '16 at 20:28
  • 1
    @harekuin I mentioned it because, per C11 §7.21.6.7/2, regarding `sscanf`, "If copying takes place between objects that overlap, the behavior is undefined." - `buffer` certainly overlaps with `buffer`. – WhozCraig Aug 11 '16 at 21:08

2 Answers2

2

You seem to be trying to create an array of pointers. So let me show you what that looks like

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXT 10

int main( void )
{
    char s[100]="search=cat+or+dog+store";
    char buffer[100];
    char **search = calloc( MAXT, sizeof(char *) );
    if ( sscanf( s, "search=%s", buffer ) != 1 )
        return 1;
    int t = 0;
    char *token = strtok( buffer, "+" );
    while ( token != NULL && t < MAXT )
    {
        search[t++] = token;
        token = strtok( NULL, "+" );
    }
    for ( int i = 0; i < t; i++ )
        printf( "%s\n", search[i] );
    free( search );
}

Things to look for

  • search is declared as a char ** meaning pointer to a char pointer, which can be used like an array of char pointers
  • in the calloc, the allocation is for 10 items of type char *, i.e. an array of 10 pointers
  • in the sscanf, the input and output strings must not be the same string. I changed the arguments so that s is the input, and buffer is the output. Also, you should always check that the return value from sscanf is equal to the number of items requested.
  • in the while loop, I've added a check t < MAXT to avoid running past the end of the pointer array
  • search is an array of pointers, and strtok returns a pointer, so the line search[t++]=token; stores the pointer in the array. The string itself is still in the buffer.
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • 1
    @harekuin Note: that this works because `strtok` replaces the delimiter ('+') with a null char. – 001 Aug 11 '16 at 20:45
  • omg you guys user3386109 thank you so much for the really in depth explanation and @JohnnyMopp for all the links you've send me and the comments! this helped a lot! – harekuin Aug 12 '16 at 04:54
  • just a quick question. why dont i need to type cast calloc? i thought it was mandatory – harekuin Aug 12 '16 at 05:12
  • @harekuin In C++, it's mandatory. But in C, [it's better *not* to cast the return from `malloc` and friends](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – user3386109 Aug 12 '16 at 05:48
1

This line here:

strcpy(&search[k],"\0");

What you are doing is adding the string literal "\0" to the k'th position in memory (which works... but gross). I believe you are trying to do this:

search[k] = '\0'

Notice the single quotes ('') that is a character rather than a string literal.

You should also not be casting a malloc: char *search = (char *)malloc(...)

MAINLY:

You should also consider that printf("%s", string) only prints up until the nearest terminator ('\0') in 'string'. Reference here.

So check what you are buffering, and see if you can build any new conclusions...

And, when you print your string, you only need to printf("%s", search)

I highly suggest you use malloc(), especially for strings. Because calloc() initiates all values to zero. And '\0' == 0, so you could be making it more difficult for yourself to diagnose.

Community
  • 1
  • 1
Matthew
  • 145
  • 11
  • i originally had a printf statement inside the while loop to check the buffer and the token and the portion that was put into the malloc. it works fine inside the loop. but the moment i leave the while loop smt goes wrong. i originally also had written the code to be like this: while(tok!=NULL) { strcpy(search,tok); search++; tok=strtok(NULL,"+"); } i was under the impression we have to dereference in order to put smt inside a malloc but apparently not??? i dont get how this works either. (and still doesnt once i leave the loop) – harekuin Aug 11 '16 at 20:24
  • I think what would help your understanding is the fact that `search[5] == *(search + 5)`... So using this, you may be able to see what you are doing when you use `strcpy(&search[k]...)` – Matthew Aug 11 '16 at 20:27