как поместить проанализированную строку в malloc/calloc/динамическую память?

Итак, я отвечаю на несколько практических вопросов для предстоящего выпускного экзамена. и у меня большие проблемы с динамической памятью.

Таким образом, вопрос состоит в том, чтобы в основном проанализировать два разных источника и сравнить их, чтобы найти похожие слова. (один из файла csv и один из ввода cgi)

поэтому я решил использовать malloc/calloc, чтобы поместить строку в каждый слот массива, а затем сравнить каждый слот. но у меня есть некоторые проблемы с моим кодом:

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. часть, которую я поместил между * *, которую я поместил, чтобы проверить, были ли строки помещены внутрь calloc. но ничего не распечатывается или что-то странное распечатывается. тот же код использовался для последней нижней части, и они оба либо пусты, либо только распечатывают странную фрагментированную часть кода.
  2. когда я помещаю бесплатно (csv) и бесплатно (поиск), он говорит, что «освобождаемый указатель не был выделен». Я просмотрел это, но я не могу найти ответ, почему он это делает?

Спасибо!


person harekuin    schedule 11.08.2016    source источник


Ответы (2)


Кажется, вы пытаетесь создать массив указателей. Итак, позвольте мне показать вам, как это выглядит

#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 );
}

Что искать

  • search объявляется как char **, означающий указатель на указатель char, который можно использовать как массив указателей char.
  • в calloc выделено 10 элементов типа char *, т.е. массив из 10 указателей
  • в sscanf входные и выходные строки не должны совпадать. Я изменил аргументы так, чтобы s было входом, а buffer — выходом. Кроме того, вы всегда должны проверять, что возвращаемое значение из sscanf равно количеству запрошенных элементов.
  • в цикле while я добавил проверку t < MAXT, чтобы избежать выхода за конец массива указателей
  • search — это массив указателей, а strtok возвращает указатель, поэтому строка search[t++]=token; хранит указатель в массиве. Сама строка все еще находится в buffer.
person user3386109    schedule 11.08.2016
comment
@harekuin Примечание: это работает, потому что strtok заменяет разделитель ('+') нулевым символом. - person Johnny Mopp; 11.08.2016
comment
omg, ребята, user3386109, большое спасибо за действительно подробное объяснение и @JohnnyMopp за все ссылки, которые вы мне прислали, и комментарии! это очень помогло! - person harekuin; 12.08.2016
comment
просто быстрый вопрос. почему мне не нужно набирать cast calloc? я думал это обязательно - person harekuin; 12.08.2016
comment
@harekuin В C++ это обязательно. Но в C лучше не возвращать от malloc и друзей. - person user3386109; 12.08.2016

Вот эта строка:

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

Что вы делаете, так это добавляете строковый литерал "\0" в k-ю позицию в памяти (что работает... но грубо). Я считаю, что вы пытаетесь сделать это:

search[k] = '\0'

Обратите внимание на одинарные кавычки (''), которые являются символом, а не строковым литералом.

Вы также не должны приводить malloc: char *search = (char *)malloc(...)

ГЛАВНОЕ:

Вы также должны учитывать, что printf("%s", string) печатается только до ближайшего терминатора ('\0') в «строке». См. здесь.

Так что проверьте, что вы буферизуете, и посмотрите, сможете ли вы сделать какие-то новые выводы...

И когда вы печатаете свою строку, вам нужно всего лишь printf("%s", search)

Я настоятельно рекомендую использовать malloc(), особенно для строк. Потому что calloc() обнуляет все значения. И '\0' == 0, так что вы можете затруднить себе диагностику.

person Matthew    schedule 11.08.2016
comment
изначально у меня был оператор printf внутри цикла while для проверки буфера, токена и части, которая была помещена в malloc. он отлично работает внутри цикла. но в тот момент, когда я покидаю цикл while, smt идет не так. изначально я также написал такой код: while(tok!=NULL) { strcpy(search,tok); поиск++; tok=strtok(NULL,+); } у меня сложилось впечатление, что мы должны разыменовать, чтобы поместить smt внутри malloc, но, видимо, нет??? я тоже не понимаю, как это работает. (и до сих пор не выходит из цикла) - person harekuin; 11.08.2016
comment
Я думаю, что поможет вашему пониманию тот факт, что search[5] == *(search + 5)... Итак, используя это, вы сможете увидеть, что вы делаете, когда используете strcpy(&search[k]...) - person Matthew; 11.08.2016