2014-01-04 3 views
-2

Я пытаюсь сохранить данные csv в массиве для использования в других функциях. Я понимаю, что strdup хорош для этого, но я не уверен, как заставить его работать для моей ситуации. Любая помощь приветствуется!Как преобразовать мой malloc + strcpy в strdup в C?

Данные хранятся в структуры:

typedef struct current{ 
    char **data; 
}CurrentData; 

Функция вызова:

int main(void){ 
    int totalProducts = 0; 
    CurrentData *AllCurrentData = { '\0' }; 
    FILE *current = fopen("C:\\User\\myfile.csv", "r"); 

    if (current == NULL){ 
     puts("current file data not found"); 
    } 
    else{ 
     totalProducts = getCurrentData(current, &AllCurrentData); 
    } 
fclose(current); 
return 0; 
} 

Как распределенную память;

int getCurrentData(FILE *current, CurrentData **AllCurrentData){ 

*AllCurrentData = malloc(totalProducts * sizeof(CurrentData)); 

    /*allocate struct data memory*/ 
    while ((next = fgetc(current)) != EOF){             
     if (next == '\n'){ 
      (*AllCurrentData)[newLineCount].data = malloc(colCount * sizeof(char*)); 
      newLineCount++; 
     } 
    } 
    newLineCount = 0; 
    rewind(current); 

    while ((next = fgetc(current)) != EOF && newLineCount <= totalProducts){      

     if (ch != '\0'){ 
      buffer[i] = ch; 
      i++; 
      characterCount++; 
     } 

     if (ch == ',' && next != ' ' || ch == '\n' && ch != EOF){ 
      if (i > 0){ 
       buffer[i - 1] = '\0'; 
      } 
      length = strlen(buffer); 
      /*(*AllCurrentData)[newLineCount].data[tabCount] = malloc(length + 1);  /* originally was using strcpy */ 
      strcpy((*AllCurrentData)[newLineCount].data[tabCount], buffer); 
      */ 
      (*AllCurrentData)[newLineCount].data[tabCount] = strdup(buffer); /* something like this? */ 

      i = 0; 
      tabCount++; 

      for (j = 0; j < BUFFER_SIZE; j++){ 
       buffer[j] = '\0'; 
      } 
     } 
+0

Это еще не полный код. У вас есть несколько переменных, которые не объявлены или не заданы. Невозможно точно сказать, что делает код из этих фрагментов. Также неясно, что должен содержать тип CurrentData. –

+0

Похоже, что вы хотите открыть файл, содержащий строки текста, в этом случае текст разделенных запятыми значений и прочитать каждую строку в массиве строковых буферов, где каждый элемент массива указывает на выделенную область памяти, содержащую текстовая строка. Результатом должен быть массив указателей на строки, где порядок строк совпадает с порядком строк в файле. Поэтому массив [0] должен указывать на буфер, содержащий текст первой строки текста в файле. Это то, что вы хотите сделать? –

+0

На первый взгляд 'strdup' не ваша проблема; ваша настоящая проблема - исчерпывающее распределение. Например, вы дважды передаете файл и считаете символы новой строки в первом проходе. Это нормально, но почему вы выделяете перед этим проходом, когда вы не знаете, сколько выделить? –

ответ

0

Вы определяете ptr AllCurrentData, но вы должны установить его в NULL.

CurrentData* AllCurrentData = NULL;

В getCurrentData вы используете totalProducts, который кажется немного странным , поскольку она является локальной переменной в основной(), либо у вас есть еще один глобальную переменную с тем же именем, или есть ошибка.

**data внутри структуры кажется странным, вместо этого, возможно, вы хотите, чтобы проанализировать линию csv и создать для них подходящие элементы. У вас уже есть массив CurrentData, поэтому кажется странным иметь другой массив внутри структуры - я просто догадываюсь, потому что вы не объяснили эту часть.

Поскольку файл csv используется на основе строки, используйте fgets() для чтения одной строки из файла, затем проанализируйте строку, используя, например, strtok или просто проверка буфера после разделителей. Здесь strdup может вступить в игру, , когда вы вытащили токен, сделайте strdup на нем и сохраните его в своей структуре .

char line[255]; 
if (fgets(line,sizeof(line),current) != NULL) 
{ 
    char* token = strdup(strtok(line, ",")); 
    ... 
} 

Вместо выделения большого буфера, который может быть достаточно (или нет) использовать перераспределить увеличить буфер, как вы читаете из файла.

Это говорит о более быстрых способах извлечения данных из csv-файла, например. вы можете прочитать весь файл с помощью fread, затем найдите разделители и установите их в \ 0 и создайте массив указателей на символы в буфере.

+0

Спасибо за отзыв о извлечении данных csv, я думаю, что перепишу программу, используя предложенный вами метод. – TinMan

0

Хорошо, я не буду комментировать другие части вашего кода, но вы можете использовать strdup, чтобы избавиться от этой линии (*AllCurrentData)[newLineCount].data = malloc(colCount * sizeof(char*));, и эта линия (*AllCurrentData)[newLineCount].data[tabCount] = strdup(buffer); /* something like this? */ и заменить их следующим образом: (*AllCurrentData)[newLineCount].data = strdup(buffer);

0

Чтобы функция считывалась в массиве строк, я хотел бы начать со следующего подхода. Это не было проверено или даже составлено, но это исходное место.

В этом примере имеется ряд проблем. Размер временного буфера 4K символов может быть или не быть достаточно большим для всех строк в файле. В файле может быть больше строк текста, чем элементов в массиве указателей, и нет никакой информации о том, что это произошло.

Усовершенствования в этом могли бы улучшить обработку ошибок.Также он может быть изменен таким образом, что массив указателей выделяется в функции с некоторой большой суммой, а затем, если в файле больше элементов, чем элементов массива, с использованием функции realloc() для увеличения массива указателей на некоторый размер. Возможно, также проверка размера файла и использование средней длины строки текста будет подходящей для обеспечения начального размера массива указателей.

// Read lines of text from a text file returning the number of lines. 
// The caller will provide an array of char pointers which will be used 
// to return the list of lines of text from the file. 
int GetTextLines (FILE *hFile, char **pStringArrays, int nArrayLength) 
{ 
    int iBuffSize = 4096; 
    int iLineCount = 0; 
    char tempBuffer [4096]; 

    while (fgets (tempBuffer, iBuffSize, hFile) && iLineCount < nArrayLength) { 
     pStringArrays[iLineCount] = malloc ((strlen(tempBuffer) + 1) * sizeof (char)); 
     if (! pStringArrays[iLineCount]) 
      break; 
     strcpy (pStringArrays[iLineCount], tempBuffer); 
     iLineCount++; 
    } 
    return iLineCount; 
} 
Смежные вопросы