我正在尝试创建一个程序,该程序接受一个输入文件,并根据每行末尾的数字按升序将其排序到新的输出文件。例如,如果输入文件包含以下三行:
a good man 50
65
better are 7
相应的排序输出文件将是三行但已排序:
better are 7
a good man 50
65
我到目前为止的代码:
int sortLines(char * inputFileName, char * outputFileName)
{
FILE *fpin = fopen(inputFileName, "r");//open file to to read
if (!fpin)
{
printf("Error in file opening\n");
exit (-1);
}
FILE *fpout = fopen(outputFileName, "w");//open file to to write
if (!fpout)
{
printf("Error in opfile opening\n");
exit (-1);
}
char file[10][1024];
int i = 0;
while(fgets(file[i], sizeof(file[i]), fpin))
i++;
int total = i;
for(i = 0; i<total; ++i)
printf("%s", file[i]);
return 0;
}
答案 0 :(得分:2)
从注释继续,您可以将行读入一个结构(包含行和一个int),然后使用strrchr
查找每行中的最后一个空格(或者如果为null,则只需要整个()),使用strtol
或atoi
等转换字符串以设置struct的int
字段。然后,基于int
成员对结构进行排序是一件简单的事情。我将把读数留给你的结构,排序的例子是:
#include <stdio.h>
#include <stdlib.h>
#define MAXL 32
struct data {
char line[MAXL];
int n;
};
int compare_n (const void *a, const void *b)
{
struct data *ia = (struct data *)a;
struct data *ib = (struct data *)b;
return (int)(ia->n - ib->n);
}
int main (void)
{
struct data lines[] = {{"a good man 50", 50}, {"65", 65}, {"better are 7", 7}};
size_t nstr = sizeof lines / sizeof *lines;
size_t i = 0;
qsort (lines, nstr, sizeof *lines, compare_n);
for (i = 0; i < nstr; i++)
printf (" %s\n", lines[i].line);
return 0;
}
<强>输出强>
$ ./bin/struct_sort_int
better are 7
a good man 50
65
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 64
/* simple struct holding char array and int */
struct data {
char line[MAXL];
int n;
};
/* qsort comparison function for int 'n' */
int compare_n (const void *a, const void *b)
{
struct data *ia = (struct data *)a;
struct data *ib = (struct data *)b;
return (int)(ia->n - ib->n);
}
int main (int argc, char **argv)
{
if (argc < 2 ) { /* validate at least 1 argument provided */
fprintf (stderr, "error: insufficient input, usage: %s filename\n", argv[0]);
return 1;
}
struct data lines[MAXL] = {{{0}, 0}}; /* array of struct */
char *ln = NULL; /* buffer for getline, getline allocates */
size_t n = 0; /* initial size of buf, 0 getline decides */
ssize_t nchr = 0; /* getline return, no. of chars read */
size_t idx = 0; /* index for array of struct */
size_t i = 0; /* general iteration variable */
FILE *fp = NULL; /* file pointer for input file */
if (!(fp = fopen (argv[1], "r"))) { /* validate file open */
fprintf (stderr, "error: file open failed. '%s'\n", argv[1]);
return 1;
}
/* read each line in file */
while ((nchr = getline (&ln, &n, fp)) != -1)
{
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0; /* strip newline or carriage rtn */
if (!nchr) continue; /* skip blank lines */
if (nchr > MAXL - 1) { /* test for line > MAXL -1 */
fprintf (stderr,
"warning: line will exceeded %d chars.\n", MAXL);
continue; /* number at end invalid */
}
strcpy (lines[idx].line, ln); /* copy to struct.line */
char *p = NULL;
if (!(p = strrchr (ln, ' '))) /* pointer to last space */
p = ln; /* if no space, then line */
lines[idx].n = atoi (p); /* convert string to int */
idx++; /* increment index */
if (idx == MAXL) { /* if MAXL read, break */
fprintf (stderr, "warning: %d lines read.\n", MAXL);
break;
}
}
if (fp) fclose (fp); /* close input file */
if (ln) free (ln); /* free line buffer mem */
qsort (lines, idx, sizeof *lines, compare_n); /* sort struct */
for (i = 0; i < idx; i++) /* print sorted array */
printf (" %s\n", lines[i].line);
return 0;
}
如果您有任何疑问,请查看并告知我们。我的测试数据在dat/endno.txt
文件中。当我有机会时,我会添加评论。
注意:已更新为跳过空白行并检查行长度与MAXL
之间的关系,以消除写入超出行尾的可能性,并跳过将被截断的行,这些行将在结束无效。
struct
静态分配的数组以下是使用两个2D数组的示例,一个用于lines
,另一个用于保存原始行索引和行尾的数字。与下面动态分配的示例不同,此示例仅限于从文件中读取MAXL
行或每行不超过MAXS
个字符。如果一行长度恰好为MAXS
个字符(包括空终止符),则必须将其丢弃,因为无法知道结尾处的数字是否仍然有效。包含行索引和末尾数字的2D数组根据末尾的数字进行排序,然后根据原始行索引打印行,从而导致行按编号顺序打印。虽然这可能看起来更简单,但它比使用struct
或下面动态分配方法的方法更受限制。这是我能想到的所有事情。祝好运。如果您有疑问,请删除一行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 64
#define MAXS 128
int cmpint (const void *a, const void *b);
int main (int argc, char **argv) {
if (argc < 2 ) { /* validate at least 1 argument provided */
fprintf (stderr, "error: insufficient input, usage: %s filename\n", argv[0]);
return 1;
}
int numidx[MAXL][2] = {{0}}; /* array of integers */
char lines[MAXL][MAXS] = {{0}}; /* array of strings */
char ln[MAXS] = {0}; /* buffer for fgets, MAXS in length */
ssize_t nchr = 0; /* getline return, no. of chars read */
size_t idx = 0; /* index for array of struct */
size_t i = 0; /* general iteration variable */
FILE *fp = NULL; /* file pointer for input file */
if (!(fp = fopen (argv[1], "r"))) { /* validate file open */
fprintf (stderr, "error: file open failed. '%s'\n", argv[1]);
return 1;
}
/* read each line in file */
while (fgets (ln, MAXS, fp) != NULL)
{
nchr = strlen (ln); /* get length of ln */
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0; /* strip newline or carriage rtn */
if (!nchr || nchr == MAXS - 2) /* skip blank lines + full */
continue; /* lines (end no. invalid) */
strcpy (lines[idx], ln); /* copy ln to lines[idx] */
char *p = NULL;
if (!(p = strrchr (ln, ' '))) /* pointer to last space */
p = ln; /* if no space, then line */
numidx[idx][0] = atoi (p); /* save end no. in array */
numidx[idx][1] = idx; /* save line index in array */
idx++; /* increment index */
if (idx == MAXL) { /* if MAXL read, break */
fprintf (stderr, "warning: %d lines read.\n", MAXL);
break;
}
}
fclose (fp);
qsort (numidx, idx, sizeof (int) * 2, cmpint);/* sort array */
for (i = 0; i < idx; i++) /* print sorted array */
printf (" %s\n", lines[numidx[i][1]]);
return 0;
}
/* qsort integer compare function */
int cmpint (const void *pa, const void *pb )
{
const int *a = pa;
const int *b = pb;
if (a[0] < b[0])
return -1;
return (b[0] < a[0]);
}
struct
,动态分配数组要使用结构来保存字符串数字,可以使用2个数组。一个用于保持字符串,另一个用于保存原始行索引和数字在行尾(2个整数)的2D数组。然后qsort
(最后的数字)元素上的整数数组,然后遍历每一行,根据排序数组的行索引值按排序顺序打印出行。这被设置为处理任何长度的行并根据需要重新分配行数(在每个数组中)。由于动态分配可能有点多,我也在研究静态数组版本,但是在我有时间之前它将是明天。这是第一个版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 64
int cmpint (const void *a, const void *b);
char **realloc_char (char **sp, size_t *n);
int **realloc_int (int **ip, size_t *n);
int main (int argc, char **argv) {
if (argc < 2 ) { /* validate at least 1 argument provided */
fprintf (stderr, "error: insufficient input, usage: %s filename\n", argv[0]);
return 1;
}
int **numidx = NULL; /* array of pointers-to-pointer-to-int */
char **lines = NULL; /* array of pointer-to-pointer-to-char */
char *ln = NULL; /* buffer for getline, getline allocates */
size_t n = 0; /* initial size of buf, 0 getline decides */
ssize_t nchr = 0; /* getline return, no. of chars read */
size_t idx = 0; /* index for array of struct */
size_t i = 0; /* general iteration variable */
size_t maxl = MAXL; /* holds current allocation size of arrays */
FILE *fp = NULL; /* file pointer for input file */
if (!(fp = fopen (argv[1], "r"))) { /* validate file open */
fprintf (stderr, "error: file open failed. '%s'\n", argv[1]);
return 1;
}
/* allocate MAXL pointers to int* */
if (!(numidx = calloc (MAXL, sizeof *numidx))) {
fprintf (stderr, "error: memory allocation failed.\n");
return 1;
}
/* allocate MAXL pointers to char* */
if (!(lines = calloc (MAXL, sizeof *lines))) {
fprintf (stderr, "error: memory allocation failed.\n");
return 1;
}
/* read each line in file */
while ((nchr = getline (&ln, &n, fp)) != -1)
{
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0; /* strip newline or carriage rtn */
if (!nchr) continue; /* skip blank lines */
lines[idx] = strdup (ln); /* copy ln to lines[idx] */
/* allocate space for 2 int at numidx[idx] */
if (!(numidx[idx] = calloc (2, sizeof **numidx))) {
fprintf (stderr, "error: memory allocation failed.\n");
return 1;
}
char *p = NULL;
if (!(p = strrchr (ln, ' '))) /* pointer to last space */
p = ln; /* if no space, then line */
numidx[idx][0] = atoi (p); /* save end no. in array */
numidx[idx][1] = idx; /* save line index in array */
idx++; /* increment index */
if (idx == maxl) { /* if idx = maxl reallocate */
size_t tsz = maxl; /* tmp var, each get maxl */
numidx = realloc_int (numidx, &tsz);
lines = realloc_char (lines, &maxl);
}
}
if (ln) free (ln);
fclose (fp);
qsort (numidx, idx, sizeof *numidx, cmpint); /* sort struct */
for (i = 0; i < idx; i++) /* print sorted array */
printf (" %s\n", lines[numidx[i][1]]);
for (i = 0; i < idx; i++) { /* free allocated memory */
free (numidx[i]);
free (lines[i]);
}
free (numidx);
free (lines);
return 0;
}
/* qsort integer compare function */
int cmpint (const void *a, const void *b)
{
const int **ia = (const int **)a;
const int **ib = (const int **)b;
return (*ia)[0] - (*ib)[0];
}
/** realloc an array of pointers to strings setting memory to 0.
* reallocate an array of character arrays setting
* newly allocated memory to 0 to allow iteration
*/
char **realloc_char (char **sp, size_t *n)
{
char **tmp = realloc (sp, 2 * *n * sizeof *sp);
if (!tmp) {
fprintf (stderr, "Error: struct reallocation failure.\n");
// return NULL;
exit (EXIT_FAILURE);
}
sp = tmp;
memset (sp + *n, 0, *n * sizeof *sp); /* memset new ptrs 0 */
*n *= 2;
return sp;
}
/** realloc an array of pointers to int* setting memory to 0.
* reallocate an array of integer arrays setting
* newly allocated memory to 0 to allow iteration
*/
int **realloc_int (int **ip, size_t *n)
{
int **tmp = realloc (ip, 2 * *n * sizeof *ip * 4);
if (!tmp) {
fprintf (stderr, "Error: struct reallocation failure.\n");
// return NULL;
exit (EXIT_FAILURE);
}
ip = tmp;
memset (ip + *n, 0, *n * sizeof *ip * 4); /* memset new ptrs 0 */
*n *= 2;
return ip;
}
答案 1 :(得分:0)
您可以将整个文件读入单个缓冲区,创建一个结构数组,其中包含指向行的指针和每行末尾的值(扫描换行符),然后按值对结构数组进行排序,以及根据排序的结构数组中的指针输出数据。