我需要对类似于以下文件的内容进行排序:
Key: 2 rec:1 2 3 4 5 6 ...
Key: 3 rec:7 8 9 10 11 ...
Key: 1 rec:A B C D E F ...
变为
Key: 1 rec:A B C D E F ...
Key: 2 rec:1 2 3 4 5 6 ...
Key: 3 rec:7 8 9 10 11 ...
如果我们在键的rec(记录)中有未分类的内容,它将保持不变!因为排序是基于密钥的。我想使用C中定义的qsort()进行排序。我有一个想法是使用strtok将从文件中读取的每一行分解为可管理的数组但是我不是,如果这是找到密钥号的最佳方式,以便使用来自C库的qsort对它们进行排序。
P.S。:输入文件的每一行包括一个键,如Key:1 rec:A B C D E F ... 此外,我们不会对密钥中的记录进行排序。
答案 0 :(得分:3)
要在c中执行此操作,请使用sscanf,您可以获得一种正则表达式来提取所需的整数:
int comp(const void *str1, const void *str2) {
char *a = *(char **)str1, *b = *(char **)str2;
int key1, key2;
sscanf(a, "%*s%d", &key1);
sscanf(b, "%*s%d", &key2);
return key1-key2;
}
//Call the function qsort like so
qsort(/*char **/lines, /*int*/numElements, /*unsigned*/ sizeof (char*), comp);
不知道如何在c ++中使用regex库,但sscanf
仍然有效。 c ++ 11中的完整工作示例:
#include <iostream>
#include <cstdio>
#include <deque>
#include <string>
#include <algorithm>
int main() {
//Using fstream, read in each line of the file into a string using getline(...)
std::deque<std::string> lines = {
"Key: 2 rec:1 2 3 4 5 6",
"Key: 3 rec:7 8 9 10 11",
"Key: 1 rec:A B C D E F",
"Key: 4 rec:1 2 3 4 5 6"
}; //Store each in a deque object
//using std::sort
std::sort(lines.begin(), lines.end(), []( const std::string &str1, const std::string &str2 ) {
int key1, key2;
sscanf(str1.c_str(), "%*s%d", &key1);
sscanf(str2.c_str(), "%*s%d", &key2);
return (key1 < key2);
});
for (auto sortedkeys: lines)
std::cout << sortedkeys << "\n";
return 0;
}
答案 1 :(得分:1)
如果密钥长度不同,则应避免使用strncmp
并逐行读取,然后通过使用从第[5]行到下一个空格的循环来获取键值(或者使用strtok
与空间的分隔符)。
重复此操作直到EOF
。将键值存储在数组或列表中。
下一个排序数组或列表。
现在使用strstr
在文件中找到已排序数组中Key的值,并将匹配的行复制到新文件中。在使用strstr
转换密钥到字符串之前。
如果你想避免复制到新文件,需要使用fseek
和修改行在行之间移动文件指针。
答案 2 :(得分:1)
如果你必须写C,它不需要那么长或复杂。如果你吝啬错误检查,你可以简化它。
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern void err_exit(const char *fmt, ...);
typedef struct data
{
char *line;
int key;
} data;
static int cmp_data(const void *v1, const void *v2)
{
const data *d1 = v1;
const data *d2 = v2;
if (d1->key < d2->key)
return -1;
else if (d1->key > d2->key)
return +1;
else
return 0;
}
int main(void)
{
char buffer[4096];
data *array = 0;
size_t array_len = 0;
size_t array_max = 0;
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
if (array_len >= array_max)
{
size_t new_size = (array_max + 2) * 2;
void *space = realloc(array, new_size * sizeof(data));
if (space == 0)
err_exit("Out of memory (1)");
array = space;
array_max = new_size;
}
array[array_len].line = strdup(buffer);
if (array[array_len].line == 0)
err_exit("Out of memory (2)");
if (sscanf(array[array_len].line, "%*s %d", &array[array_len].key) != 1)
err_exit("Format error - no number in right place in: %.20s...\n",
array[array_len].line);
//printf("%3zu:%.10d: %s", array_len, array[array_len].key,
// array[array_len].line);
array_len++;
}
qsort(array, array_len, sizeof(data), cmp_data);
for (size_t i = 0; i < array_len; i++)
fputs(array[i].line, stdout);
return 0;
}
void err_exit(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
putc('\n', stderr);
exit(EXIT_FAILURE);
}
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void sort_file(const char *i_file, const char *o_file);
int main(int argc, char **argv)
{
if (argc > 1)
{
for (int i = 1; i < argc; i++)
sort_file(argv[i], argv[i]);
}
else
sort_file("/dev/stdin", "/dev/stdout");
return 0;
}
typedef struct data
{
char *line;
int key;
} data;
static int cmp_data(const void *v1, const void *v2)
{
const data *d1 = v1;
const data *d2 = v2;
if (d1->key < d2->key)
return -1;
else if (d1->key > d2->key)
return +1;
else
return 0;
}
static void err_exit(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
putc('\n', stderr);
exit(EXIT_FAILURE);
}
void sort_file(const char *i_file, const char *o_file)
{
char buffer[4096];
data *array = 0;
size_t array_len = 0;
size_t array_max = 0;
FILE *i_fp = fopen(i_file, "r");
if (i_fp == 0)
err_exit("Failed to open file %s for reading", i_file);
while (fgets(buffer, sizeof(buffer), i_fp) != 0)
{
if (array_len >= array_max)
{
size_t new_size = (array_max + 2) * 2;
void *space = realloc(array, new_size * sizeof(data));
if (space == 0)
err_exit("Out of memory (1)");
array = space;
array_max = new_size;
}
array[array_len].line = strdup(buffer);
if (array[array_len].line == 0)
err_exit("Out of memory (2)");
if (sscanf(array[array_len].line, "%*s %d", &array[array_len].key) != 1)
err_exit("Format error - no number in right place in: %.20s...\n",
array[array_len].line);
//printf("%3zu:%.10d: %s", array_len, array[array_len].key,
// array[array_len].line);
array_len++;
}
fclose(i_fp);
qsort(array, array_len, sizeof(data), cmp_data);
FILE *o_fp = fopen(o_file, "w");
if (o_fp == 0)
err_exit("Failed to open file %s for writing", o_file);
for (size_t i = 0; i < array_len; i++)
fputs(array[i].line, o_fp);
fclose(o_fp);
}
如果您的系统不支持/dev/stdin
和/dev/stdout
,那么您必须将接口修改为sort_file()
,可能是:
void sort_file(const char *i_file, FILE *ifp, const char *o_file, FILE *ofp);
然后,您决定如果ifp
不为空,则将其用于输入 - 否则您打开i_file
指定的文件。类似地输出:如果ofp
不为null,则使用它 - 否则,打开o_file
指定的文件。 main()
和sort_file()
正文中的更改非常简单。