我刚刚进入C,我认为这将是一个很好的练习。我一直在试图尝试从文件读取fgets,我只是做错了什么。我想输入要读取的文件名,输入要输出的文件名,创建该文件,对其进行排序(只是一个单词列表),然后将已排序的列表转储到创建的文件中。我知道我应该做的事情如下:
char strIn[25];
printf("Enter a source filename: ");
fgets(strIn, 25, stdin);
printf("You entered: %s \n", strIn);
FILE *infile;
infile = fopen(strIn, "r");
if (infile == NULL){
printf("Unable to open file.");
}
char strOut[25];
printf("Enter a destination filename: ");
fgets(strOut, 25, stdin);
printf("You entered: %s \n", strOut);
FILE *outfile;
任何帮助表示赞赏!谢谢
答案 0 :(得分:3)
fgets
将换行符\n
放在缓冲区的末尾。所以你需要删除它。
int length = strlen(strIn);
if ( length > 0 && strIn[length-1] == '\n' )
strIn[length-1] = '\0';
答案 1 :(得分:2)
你走在正确的轨道上。 qsort会做你想要的。这里使用的方法不可扩展;一切都保存在内存中,静态分配会让事情变得非常快,但它可以作为一个玩具示例。目前,一旦输入文件中有超过1000行,它就会中断。
# include <stdio.h>
# include <string.h>
#define MAXNAMELEN 100
#define MAXLINELEN 100
#define MAXITEMS 1000
int main(int argc, char ** argv) {
FILE * infile, * outfile;
// Statically allocated -- dastardly!
char name[MAXNAMELEN];
char line[MAXLINELEN];
char lines[MAXITEMS][MAXLINELEN];
int i, items = 0;
printf("Enter a source filename: ");
fgets(name, sizeof(name), stdin);
name[strlen(name)-1] = '\0'; // strip newline
// No error checking -- ANYWHERE -- dastardly!
infile = fopen(name, "r");
while (fgets(line, sizeof(line), infile)) {
strcpy(lines[items], line);
items++;
}
qsort(lines, items, MAXLINELEN, strcmp);
printf("Enter a destination filename: ");
fgets(name, sizeof(name), stdin);
name[strlen(name)-1] = '\0'; // strip newline
outfile = fopen(name, "w");
for (i=0; i<items; i++) {
fputs(lines[i], outfile);
}
fclose(infile);
fclose(outfile);
}
答案 2 :(得分:1)
现在进行动态分配和错误检查(可能比上面的版本有所改进)。排序/usr/share/dict/words
(99171行)完全没问题。仍然需要将整个数组保存在内存中。请参阅External Sorting了解相关方法。
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
#define CHUNKLEN 100
#define INITITEMS 1000
/* Reads a string from stream into buffer until a newline or EOF.
buffer is dynamically allocated (and reallocated if necessary)
to ensure the string fits. Returns the number of characters put
into the buffer (zero if EOF and no characters read), or -1 on error. */
int unlimited_read(char ** buffer, FILE * stream) {
int bufl = CHUNKLEN;
int strl = 0;
char * chunk = (char *)malloc(CHUNKLEN);
if ( (*buffer = (char *) malloc(CHUNKLEN)) == NULL ) {
perror("memory error (malloc)");
return -1;
}
while (fgets(chunk, CHUNKLEN, stream) != NULL) {
strcpy(*buffer + strl, chunk);
strl += strlen(chunk);
if ( (strl == bufl - 1 ) && *(*buffer + strl - 1) != '\n') {
// lengthen buffer
bufl += CHUNKLEN - 1;
if ( (*buffer = realloc(*buffer, bufl)) == NULL ) {
perror("memory error (realloc)");
return -1;
}
} else {
// This shouldn't fail -- we're only ever making it smaller
*buffer = realloc(*buffer, strl);
return strl;
}
} // while
// If fgets returned NULL and we are not at EOF, it didn't work
return feof(stream) ? strl : -1;
}
/* Compare two strings given pointers to those strings.
Routine is courtesy of the qsort man page */
int cmpstringp(const void *p1, const void *p2) {
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
/* Sort lines in a file. File must end with a newline. */
int main(int argc, char ** argv) {
FILE * infile, * outfile;
char * inname, * outname, *tmpstr;
char ** lines;
int ret, tmp, nlines, i, items = 0;
if (argc != 3) {
printf("Usage: %s file_to_sort output_file\n", argv[0]);
exit(EXIT_FAILURE);
}
inname = argv[1];
outname = argv[2];
if ( (lines = malloc(INITITEMS * sizeof(char *))) == NULL) {
perror("memory error (malloc)");
exit(EXIT_FAILURE);
}
nlines = INITITEMS;
infile = fopen(inname, "r");
while ((ret = unlimited_read(&lines[items], infile)) > 0) {
items++;
if (items == nlines) {
nlines += INITITEMS;
lines = realloc(lines, (nlines * sizeof(char *)));
}
}
if (ret < 0) {
printf("WARNING: possibly truncated file\n");
}
tmpstr = lines[items - 1]; // Final line in file
tmp = strlen(tmpstr);
if (tmpstr[tmp - 1] != '\n') {
printf("Error: input file does not end with newline\n");
exit(EXIT_FAILURE);
}
qsort(lines, items, sizeof(char *), cmpstringp);
outfile = fopen(outname, "w");
for (i = 0; i < items; i++) {
fputs(lines[i], outfile);
free(lines[i]);
}
free(lines);
fclose(infile);
fclose(outfile);
}