从带有 strtok + qsort 问题的行中读取
Reading from lines with strtok + qsort problem
我想创建的是一个从 {key: value}
形式的外部文件中获取行的程序。例如,我们有文件 t.dat
:
{myName: Mario}
{name2: Asdadas}
{someOtherData: _D123}
我的程序应该根据 key
的长度(在我们的例子中,myName
、name2
或 someOtherData
的长度以递减的方式对这些数据进行排序) 如果找到两个长度相同的键,则应根据 value
.
按字典顺序对它们进行排序
我通过使用 struct array
来完成此操作,它将保留文档中每一行的数据:
typedef struct Line{
char key[50];
char value[50];
}Line;
并尝试使用 fgets
(获取每一行)和 strtok
.
从文件中取出数据
这是我的全部代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 512
typedef struct Line{
char key[50];
char value[50];
}Line;
int comp(const void* a, const void* b)
{
const Line *aa = a;
const Line *bb = b;
puts(bb->key);
if (strlen(aa->key) == strlen(bb->key)) {
return strcmp(aa->key, bb->key);
}
return strlen(bb->value)-strlen(aa->value);
}
int main(int argc, char** argv)
{
if (argc != 2)
{
printf("Invalid number of args.\n");
return -1;
}
FILE *f = fopen(argv[1], "rb");
if (!f)
{
printf("Unable to open the specified file.\n");
return -2;
}
Line* ln;
char buff[MAX];
int lineNumber = 0;
int isSet = 0;
int i = 0;
while (fgets(buff, MAX, f))
{
char *p = strtok(buff, " {}:\n\r\t");
while (p)
{
char word[MAX] = "";
if (isSet == 0)
{
ln = malloc(1*sizeof(ln));
isSet = 1;
}
else if (i == 0) ln = (Line*)realloc(ln, (lineNumber+1)*sizeof(ln));
word[0] = '[=12=]';
if (i == 0) {
strcpy(word, p);
strcpy(ln[lineNumber].key, word);
i = 1;
}
else if (i == 1) {
strcpy(word, p);
strcpy(ln[lineNumber].value, word);
lineNumber++;
i = 0;
}
p = strtok(NULL, " {}:\n\r\t");
}
}
qsort(ln, lineNumber, sizeof(ln), comp);
puts("\n");
for (int i = 0; i<lineNumber; i++)
{
printf("%s\n", ln[i].key);
}
return 0;
}
问题是,第一行的数据读取不正确(我指的是 value
- "Mario"
。它包含来自 key
的元素,但是当然不是 Mario
这个词)。认为这可能来自 strtok
,但没有找到解决方案。
此外,使用提供的 comp
函数,数据排序不正确。它根本没有订购。输出与下单前一样。
我能做什么?谢谢你。如果需要更多详细信息,请告诉我,我会确保 post。
问题是
ln = (Line*)realloc(ln, (lineNumber+1)*sizeof(ln));
你想为 n 个元素保留空间,而不是为 n 个指向元素的指针保留空间,切换到
ln = realloc(ln, (lineNumber+1)*sizeof(*ln)); // Don't cast
另外,always use a temporary variable 和 realloc
:
Line *temp = realloc(ln, (lineNumber+1)*sizeof(*ln));
if (temp == NULL)
{
// raise error
}
ln = temp;
这里也一样
qsort(ln, lineNumber, sizeof(ln), comp);
每个元素占sizeof(*ln)
,不是sizeof(ln)
,转为
qsort(ln, lineNumber, sizeof(*ln), comp);
我想创建的是一个从 {key: value}
形式的外部文件中获取行的程序。例如,我们有文件 t.dat
:
{myName: Mario}
{name2: Asdadas}
{someOtherData: _D123}
我的程序应该根据 key
的长度(在我们的例子中,myName
、name2
或 someOtherData
的长度以递减的方式对这些数据进行排序) 如果找到两个长度相同的键,则应根据 value
.
我通过使用 struct array
来完成此操作,它将保留文档中每一行的数据:
typedef struct Line{
char key[50];
char value[50];
}Line;
并尝试使用 fgets
(获取每一行)和 strtok
.
这是我的全部代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 512
typedef struct Line{
char key[50];
char value[50];
}Line;
int comp(const void* a, const void* b)
{
const Line *aa = a;
const Line *bb = b;
puts(bb->key);
if (strlen(aa->key) == strlen(bb->key)) {
return strcmp(aa->key, bb->key);
}
return strlen(bb->value)-strlen(aa->value);
}
int main(int argc, char** argv)
{
if (argc != 2)
{
printf("Invalid number of args.\n");
return -1;
}
FILE *f = fopen(argv[1], "rb");
if (!f)
{
printf("Unable to open the specified file.\n");
return -2;
}
Line* ln;
char buff[MAX];
int lineNumber = 0;
int isSet = 0;
int i = 0;
while (fgets(buff, MAX, f))
{
char *p = strtok(buff, " {}:\n\r\t");
while (p)
{
char word[MAX] = "";
if (isSet == 0)
{
ln = malloc(1*sizeof(ln));
isSet = 1;
}
else if (i == 0) ln = (Line*)realloc(ln, (lineNumber+1)*sizeof(ln));
word[0] = '[=12=]';
if (i == 0) {
strcpy(word, p);
strcpy(ln[lineNumber].key, word);
i = 1;
}
else if (i == 1) {
strcpy(word, p);
strcpy(ln[lineNumber].value, word);
lineNumber++;
i = 0;
}
p = strtok(NULL, " {}:\n\r\t");
}
}
qsort(ln, lineNumber, sizeof(ln), comp);
puts("\n");
for (int i = 0; i<lineNumber; i++)
{
printf("%s\n", ln[i].key);
}
return 0;
}
问题是,第一行的数据读取不正确(我指的是 value
- "Mario"
。它包含来自 key
的元素,但是当然不是 Mario
这个词)。认为这可能来自 strtok
,但没有找到解决方案。
此外,使用提供的 comp
函数,数据排序不正确。它根本没有订购。输出与下单前一样。
我能做什么?谢谢你。如果需要更多详细信息,请告诉我,我会确保 post。
问题是
ln = (Line*)realloc(ln, (lineNumber+1)*sizeof(ln));
你想为 n 个元素保留空间,而不是为 n 个指向元素的指针保留空间,切换到
ln = realloc(ln, (lineNumber+1)*sizeof(*ln)); // Don't cast
另外,always use a temporary variable 和 realloc
:
Line *temp = realloc(ln, (lineNumber+1)*sizeof(*ln));
if (temp == NULL)
{
// raise error
}
ln = temp;
这里也一样
qsort(ln, lineNumber, sizeof(ln), comp);
每个元素占sizeof(*ln)
,不是sizeof(ln)
,转为
qsort(ln, lineNumber, sizeof(*ln), comp);