我需要列印檔案中的所有短語(短語可以以 '.'、'?' 或 '!' 結尾)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* read_file(char *name) {
FILE *file;
char *text;
long num_bytes;
file = fopen(name, "r");
if(!file) {
printf("File could not be opened!");
exit(EXIT_FAILURE);
}
fseek(file, 0, SEEK_END);
num_bytes = ftell(file);
fseek(file, 0, SEEK_SET);
text = (char*) malloc(num_bytes * sizeof(char));
fread(text, 1, num_bytes, file);
fclose(file);
return text;
}
int main(int argc, char* argv[]) {
char *text = read_file(argv[1]);
unsigned int count = 0, index=0;
char *line = (char*) malloc(sizeof(text));
for(int i = 0; i < strlen(text); i ) {
line[index] = text[i];
index ;
if(text[i] == '.' || text[i] == '?' || text[i] == '!') {
count ;
printf("[%d] %s\n", count, line);
memset(line, 0, index 1);
index = 0;
}
}
return EXIT_SUCCESS;
}
我有這樣一段代碼,但如果我的檔案是以下文本:“我的名字是瑪麗亞。我 19 歲。” 第二個短語在開頭印有''。有人可以幫忙找到一種方法來忽略這些空間嗎?謝謝
uj5u.com熱心網友回復:
首先,您有幾個問題會呼叫Undefined Behavior。在
char *line = (char*) malloc(sizeof(text));
sizeof (text)是指標 ( char *) 的大小,而不是它指向的緩沖區的長度。
sizeof (char *)取決于您的系統,但很可能是8(如果您好奇,請繼續測驗printf("%zu\n", sizeof (char *));:),這意味著line可以保存一個長度 7字串(加上空終止位元組)。
長句子很容易溢位這個緩沖區,導致UB。
(旁白:不要malloc在 C 中使用 return 。)
此外,strlen(text)可能無法正常作業,因為text可能不包括空終止位元組 ( '\0')。fread使用原始位元組,并且不理解以空字符結尾的字串的概念- 檔案不必以空字符結尾,fread也不會為您以空字符結尾的緩沖區。
您應該在read_file函式中分配一個額外的位元組
text = malloc(num_bytes 1);
text[num_bytes] = 0;
并將空終止位元組放在那里。
(旁白:保證sizeof (char)是。)1
請注意,不應依賴于ftell確定檔案的長度。
isspacefrom<ctype.h>可用于確定當前字符是否為空格。它的論點應該轉換為unsigned char. 請注意,這將包括 和 等'\t'字符'\n'。如果您只關心空格 ( text[i 1] == ' '),請使用簡單比較。
在匹配分隔符后,可以使用回圈來消耗尾隨空格。
line確保在列印之前以空值終止,如string%s所期望的那樣。
用于%u列印unsigned int.
完成后不要忘記free動態分配的記憶體。此外,認真考慮檢查任何可能失敗的庫函式都沒有這樣做。
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void pdie(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
char *read_file(char *name) {
FILE *file = fopen(name, "r");
if (!file)
pdie(name);
fseek(file, 0, SEEK_END);
long num_bytes = ftell(file);
if (-1 == num_bytes)
pdie(name);
fseek(file, 0, SEEK_SET);
char *text = malloc(num_bytes 1);
if (!text)
pdie("malloc");
if (-1 == num_bytes)
pdie(name);
text[num_bytes] = 0;
if (fread(text, 1, num_bytes, file) != num_bytes)
pdie(name);
fclose(file);
return text;
}
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "usage: %s TEXT_FILE\n", argv[0]);
return EXIT_FAILURE;
}
char *text = read_file(argv[1]);
unsigned int count = 0;
size_t length = strlen(text);
size_t index = 0;
char *line = malloc(length 1);
if (!line)
pdie("malloc");
for (size_t i = 0; i < length; i ) {
line[index ] = text[i];
if (text[i] == '.' || text[i] == '?' || text[i] == '!') {
line[index] = '\0';
index = 0;
printf("[%u] <<%s>>\n", count, line);
while (isspace((unsigned char) text[i 1]))
i ;
}
}
free(text);
free(line);
return EXIT_SUCCESS;
}
輸入檔案:
My name is Maria. I'm 19. Hello world! How are you?
stdout:
[1] <<My name is Maria.>>
[2] <<I'm 19.>>
[3] <<Hello world!>>
[4] <<How are you?>>
uj5u.com熱心網友回復:
您可以通過將相關字符與“ ”進行比較來測驗空格字符。
if(text[i] == ' ')
// text[i] is whitespace
uj5u.com熱心網友回復:
一種可能的解決方案是,當您找到句子的結尾時,前進到下一個非空白字符。您還需要確保您malloc對當前短語有足夠的記憶:
#include <ctype.h> // for isspace
...
size_t textLength = strlen(text);
// malloc based on the text length here, plus 1 for the NUL terminator.
// sizeof(text) gives you the size of the pointer, not the size of the
// memory block it points to.
char *line = malloc(textLength 1);
for(size_t i = 0; i < textLength; i ) {
line[index] = text[i];
index ;
if(text[i] == '.' || text[i] == '?' || text[i] == '!') {
count ;
printf("[%d] %s\n", count, line);
memset(line, 0, index 1);
index = 0;
// advance to the next non-whitespace char
do
{
// advance to the next char (we know the current char is not a space)
i ;
// keep advancing i while the next char is in range of the
// text and the next char is a space.
}while (i 1 < textLength && isspace(text[i 1]) != 0);
}
}
輸出:
[1] My name is Maria.
[2] I'm 19.
示范
也不需要強制轉換回傳值malloc
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/477520.html
上一篇:用鍵分隔行并存盤在不同的檔案中
下一篇:在顫振專案檔案夾中創建檔案
