Этот код корректно компилируется и работает под valgrind
.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void svnViewStatus(void)
{
FILE *file;
int i, j, k, q=0, ok;
char mystring[100000], *vect[100000], *var, last[12], first[12];
file = fopen("db_svnViewStatus.txt", "r");
if (file == NULL)
{
printf("error");
return;
}
for (i = 1; fgets(mystring, sizeof(mystring), file) != 0; i++)
{
if (i == 1) /* Skip heading */
continue;
char *space = mystring;
for (j = 1; (var = strtok(space, ";")) != NULL; space = NULL, j++)
{
if (j == 3)
{
if (i == 2)
{
strcpy(first, var);
}
strcpy(last, var);
}
if (j == 2)
{
if (q != 0)
{
ok = 1;
for (k = 0; k<q; k += 2)
{
if (strcmp(vect[k], var) == 0)
{
(*vect[k+1])++;
ok=0;
}
}
if (ok == 1)
{
vect[q] = malloc(strlen(var)+1);
strcpy(vect[q], var);
vect[q+1] = malloc(sizeof(int));
*vect[q+1] = 1;
q += 2;
}
}
else
{
vect[q] = malloc(strlen(var)+1);
strcpy(vect[q], var);
vect[q+1] = malloc(sizeof(int));
*vect[q+1] = 1;
q += 2;
}
}
}
}
fclose(file);
printf("nr: %d \n", i-2);
printf("first: %s \n", first);
printf("last: %s \n", last);
for (i=0; i<q; i = i+2)
{
printf("User %s: %d \n", vect[i], *vect[i+1]);
}
for (i=0; i<q; i=i+1)
{
free(vect[i]);
}
}
int main(void)
{
svnViewStatus();
return 0;
}
Имеет несколько уровней меньше отступов, чем оригинал. Код, идущий с правой стороны экрана, чаще всего указывает на наличие проблем. Как отмечено в комментариях, основная проблема заключалась в выражении, которое предназначалось для увеличения целого числа посредством указателя, но фактически увеличивало указатель, а не целое число. Есть пара петель for
, заменяющих петли while
, так что элемент управления цикла находится в верхней части цикла. Зачастую таким способом легче управлять циклом.
Я все еще недоволен кодом. Вы выделяете int
и обрабатываете char *
как int *
, что означает, что на 64-битной машине у вас есть 8-байтовый указатель, указывающий на 4 байта данных (и два вызова malloc()
). Если вы использовали структуру, такую как:
struct data
{
char *string;
int count;
};
struct data vect[5000];
При этом вы только выделите (продублируете) строку в следующем элементе структуры. Это было бы более компактно, и там меньше опасности ошибиться. (Вы написали бы vect[i].count++;
, и он сделал бы то, что вы хотите, без суеты, без суеты.) И вам не нужно было бы возиться с q += 2;
(или q = q + 2;
).
Этот код лучше, используя структуру. Он также проверяет распределение памяти и гарантирует, что имена, скопированные в first
и last
, не переполняются (и обнуляются). Он по-прежнему не выполняет проверку границ массива vect
, чтобы убедиться, что он не перезаписывает конец. Если при чтении файла произошла ошибка, произошла утечка памяти; очистка потребует некоторого внимания (и функции для этого).
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct data
{
char *string;
int count;
};
static void svnViewStatus(void)
{
FILE *file;
int i, q = 0;
char mystring[100000], last[12], first[12];
struct data vect[50000];
file = fopen("db_svnViewStatus.txt", "r");
if (file == NULL)
{
printf("file open error\n");
return;
}
for (i = 1; fgets(mystring, sizeof(mystring), file) != 0; i++)
{
if (i == 1) /* Skip heading */
continue;
char *space = mystring;
char *var;
for (int j = 1; (var = strtok(space, ";")) != NULL; space = NULL, j++)
{
if (j == 3)
{
if (i == 2)
{
strncpy(first, var, sizeof(first)-1);
first[sizeof(first)-1] = '\0';
}
strncpy(last, var, sizeof(last)-1);
last[sizeof(last)-1] = '\0';
}
if (j == 2)
{
int found = 0;
for (int k = 0; k < q; k++)
{
if (strcmp(vect[k].string, var) == 0)
{
vect[k].count++;
found = 1;
}
}
if (found == 0)
{
vect[q].string = strdup(var);
if (vect[q].string == 0)
{
printf("Memory allocation error\n");
return;
}
vect[q].count = 1;
q++;
}
}
}
}
fclose(file);
printf("nr: %d\n", i-1);
printf("first: %s\n", first);
printf("last: %s\n", last);
for (i = 0; i < q; i++)
{
printf("User %s: %d\n", vect[i].string, vect[i].count);
}
for (i = 0; i < q; i++)
{
free(vect[i].string);
}
}
int main(void)
{
svnViewStatus();
return 0;
}