[英]How can I navigate through an array of strings of any length in C?
理解在C中處理直接指針
這是一個代碼,適用於固定數量的項目和固定行長度的字符串數組:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXNAMELEN 100
#define MAXLINELEN 100
#define MAXITEMS 1000
int main(int argc, char ** argv) {
FILE * infile, * outfile;
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
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);
}
問題描述和代碼
如果我嘗試讀取MAXLINELEN
和MAXITEMS
的input.txt文件,程序運行正常。 現在想象一下我從一個更大的“輸入文件”中逐行讀取,其中最大行長度可以是任何東西,然后我將不得不使用字符指針( char*
)來讀取輸入。 char* linesptr[MAXITEMS];
這是我的代碼,我試圖通過換行符分隔的輸入文件逐行完成讀取。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#define MAXNAMELEN 1000
#define MAXLINELEN 1000
#define MAXITEMS 100000
char* linesptr[MAXITEMS];
int
main(int argc, char ** argv) {
FILE * infile, * outfile;
char name[MAXNAMELEN];
char line[MAXLINELEN];
int i, items = 0;
printf("Enter a source filename: ");
fgets(name, MAXNAMELEN, stdin);
name[strlen(name)-1] = '\0'; // strip newline
printf("%s infile \n",name);
infile = fopen(name, "r");
while (fgets(line, MAXLINELEN, infile)) {
int length = strlen(line);
line[length-1] = '\0';
linesptr[items] = line; *<- I am writing to the same mem location*
printf("the input string %d is : %s \n",items, linesptr[items]);
items++;
}
qsort(linesptr, 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(linesptr[i], outfile);
}
fclose(infile);
fclose(outfile);
}
問題
我將指針地址復制到數組linesptr
的第n個單元格中,其中nth是value=items
(這里是代碼中的參考行: linesptr[items] = line;
)。 所以當你打印最終的答案,我引用相同的內存地址緩沖區命名line
,在存儲位置line
總是指向最近fgets()
我理解錯誤,但我不知道如何解決這個問題。 我將不勝感激任何幫助修復代碼中的錯誤。
將該行復制到動態分配的字符串。
while (fgets(line, MAXLINELEN, infile)) {
int length = strlen(line);
if (length > 0 && line[length-1] == '\n') {
line[length-1] = '\0';
length--;
}
char *linecopy = malloc(length+1);
strcpy(linecpy, line);
linesptr[items] = linecpy;
printf("the input string %d is : %s \n",items, linesptr[items]);
items++;
}
如果你想要處理超過MAXITEMS
行,你也應該使用malloc()
來分配linesptr
。 當你達到linesptr
的當前大小時,你可以使用realloc()
來使它更長。 有關詳細代碼,請參閱從stdin,C讀取未知行數 。
請參見如何在C中輸入指向char的指針數組? 以正確的方式排序指向字符串的指針數組。
你問一個例子,所以這里是:
以下提議的代碼:
getline()
和realloc()
realloc()
。 strcspn()
刪除任何(可能的)尾隨換行符 size_t
而不是int
作為索引到數組中以避免隱式轉換 scope
qsort()
qsort()
的compare()
輔助函數 現在,建議的代碼:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXNAMELEN 1024
// prototypes
int compare(const void *, const void *);
int main( void )
{
printf("Enter a source filename: ");
char name[ MAXNAMELEN ];
if( !fgets(name, sizeof( name ), stdin) )
{
perror( "fgets for input file name failed" );
exit( EXIT_FAILURE );
}
// implied else, fgets for input file name successful
name[strcspn( name, "\n" ) ] = '\0'; // strip newline
printf("%s infile \n",name);
FILE *fp_in = fopen(name, "r");
if( !fp_in )
{
perror( "fopen for input file failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen for input file successful
char **linesarray = NULL;
size_t numLines = 0;
char *line = NULL;
size_t lineLen = 0;
while( getline( &line, &lineLen, fp_in ) != -1 )
{
char ** temp = realloc( linesarray, (numLines+1) * sizeof( char* ) );
if( !temp )
{
perror( "realloc failed" );
fclose( fp_in );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
linesarray = temp;
linesarray[ numLines ] = line;
numLines++;
// prep for next iteration
line = NULL;
lineLen = 0;
}
free( line );
fclose( fp_in );
//puts( "all file read in" );
qsort( linesarray, numLines, sizeof( char * ), compare );
//puts( "file sorted" );
printf("Enter a destination filename: ");
if( !fgets(name, sizeof(name), stdin) )
{
perror( "fgets for output file name failed" );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
// implied else, fgets() for output file name successful
name[strcspn( name, "\n" ) ] = '\0'; // strip newline
FILE *fp_out = fopen(name, "w");
if( !fp_out )
{
perror( "fopen for output file failed" );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
// implied else, fopen for output file successful
for (size_t i=0; i<numLines; i++)
{
if( fputs(linesarray[i], fp_out ) == EOF )
{
perror( "fputs failed" );
fclose( fp_out );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
}
fclose( fp_out );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
}
int compare(const void *ls, const void *rs )
{
char *leftSide = *(char**)ls;
char *rightSide = *(char**)rs;
return strcmp( leftSide, rightSide );
}
這是讀取文件(大數據),對其進行排序並將其寫入文件的完整工作解決方案:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#define MAXNAMELEN 1000
#define MAXLINELEN 5000
#define MAXITEMS 100000
char* linesptr[MAXITEMS];
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = *(const char **)name1;
const char *name2_ = *(const char **)name2;
return strcmp(name1_, name2_);
}
int
main(int argc, char ** argv)
{
FILE * infile, * outfile;
char name[MAXNAMELEN];
char line[MAXLINELEN];
int i, items = 0;
printf("Enter a source filename: ");
fgets(name, MAXNAMELEN, stdin);
name[strlen(name)-1] = '\0'; // strip newline
infile = fopen(name, "r");
while (fgets(line, MAXLINELEN, infile)) {
int length = strlen(line);
line[length-1] = '\0';
char *linecopy = malloc(length);
strcpy(linecopy, line);
linesptr[items] = linecopy;
items++;
}
qsort(linesptr, items, sizeof(char *), compare_function);
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++) {
fprintf(outfile, "%s\n", linesptr[i]);
}
fclose(infile);
fclose(outfile);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.