程式需要做到以下幾點:
- 初始化組合字串變數。
- 讀取一個不超過 256 個字符的字串 (input1) 然后:直到讀取的字串的第一個字符為 '#'
- 為新的組合字串變數分配足夠的空間來保存當前組合字串變數和新的讀取字串 (input1)。
- 然后將舊組合變數的內容復制到新的、更大的組合變數字串中。
- 然后將新讀取的字串 (input1) 連接到新組合字串的末尾。
- 釋放舊的組合字串。
- 再次將字串讀入輸入 1。
- 在用戶鍵入帶有“#”的字串后,列印出新的組合字串。
測驗輸入:我在哪里#這里
預期輸出:whereIam
實際輸出:分段錯誤(核心轉儲)
請注意,上面的空格分隔字串。再寫兩個測驗用例。
這是我自己的代碼:
#include<stdio.h>
#include<stdlib.h> // for malloc
#include<string.h> // for string funs
int main(void) {
char input1[257];
printf("Please enter a string here: ");
scanf("%6s",input1);
int input1_index = 0;
while (input1[input1_index] != '#') {
input1_index ;
}
char *combined;
combined = malloc(sizeof(char)*(input1_index 1 1));
combined[0] = '\0';
strcpy(combined,input1);
printf("%s\n",combined);
return 0;
}
如何修改我的代碼?什么是分段錯誤(核心轉儲)?謝謝你們。
uj5u.com熱心網友回復:
使用scanf,說明%Ns符在讀取非空白字符之前消耗并丟棄所有前導空白 - 在遇到尾隨空白或讀取非空白字符時停止N。
隨著輸入
where I am #here
這
char input1[257];
scanf("%6s", input1);
將導致input1包含字串的緩沖區"where"。
這個while回圈
while (input1[input1_index] != '#') {
input1_index ;
}
不處理指定的"[read strings...] until the first character of the read string is '#'"。它只是在您讀取的一個字串中搜索該'#'字符,并且如果不存在字串的有效索引(如 的情況"where"),則很容易超出該字串的有效索引。這將導致Undefined Behavior,并且肯定是您的 SIGSEGV 的原因。
您的代碼未遵循詳細說明。
需要一個回圈來使用scanfand讀取兩個或多個空格分隔的字串%s。此回圈應在scanf失敗時結束,或者讀取字串的第一個字符是'#'.
在此回圈中,您應該獲取讀取字串 ( strlen) 的字串長度并將其添加到現有字串長度。您應該分配一個該長度加一 ( ) 的新緩沖區malloc,如果分配失敗則退出回圈。
- 然后,您應該將現有字串復制到這個新緩沖區 (
strcpy)。 - 然后,您應該將讀取的字串連接到這個新緩沖區 (
strcat)。 - 然后,您應該釋放現有的字串緩沖區 (
free)。 - 然后,您應該將新字串緩沖區的指標值復制到現有的字串緩沖區變數 (
=)。
然后重復回圈。
在偽代碼中,這大致如下所示:
input := static [257]
combined := allocate [1] as ""
size := 0
exit program if combined is null
print "Enter strings: "
while read input does not begin with '#' do
add length of input to size
temporary := allocate [size 1]
stop loop if temporary is null
copy combined to temporary
concatenate input to temporary
deallocate combined
combined := temporary
end
print combined
deallocate combined
uj5u.com熱心網友回復:
其他人已經解釋了你應該做什么。但我的額外建議是接受這些詳細說明并發表評論。然后將它們中的每一個翻譯成 C 代碼:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
// initialise the combined string variable.
char *combined = malloc(1);
combined[0] = 0;
while (true) {
// read a string (input1) of no more than 256 characters
char input1[257];
if (scanf("%6s", input1) != 1) {
break;
}
// then: Until the first character of the read string is '#'
if (input1[0] == '#') {
break;
}
// allocate enough space for a new combined string variable to hold the current combined string variable and the new read-string (input1).
char *tmp = malloc(strlen(combined) strlen(input1) 1);
// then copy the contents of the old combined variable to the new, bigger, combined variable string.
strcpy(tmp, combined);
// then concatenate the newly read-string (input1) to the end of the new combined string.
strcat(tmp, input1);
// deallocate the old combined string.
free(combined);
combined = tmp; // <-- My interpretation of what the aim is
// read a string into input 1 again. <-- I guess they mean to loop
}
// After the user has typed a string with '#' print out the new combined string.
printf("%s", combined);
free(combined);
return 0;
}
請注意“初始化”是如何表示“使其成為可以稍后擴展的適當 C 字串”的。
當您閱讀任何內容時,請記住檢查閱讀是否成功。
的第一個字符input1只是 `input1[0]'。檢查它總是安全的(如果讀取成功),因為它必須是第一個字符或字串終止符。沒有錯誤檢測的風險。
分配需要添加 , 和字串終止符的combined大小input1。
復制和連接可在<string.h>.
請注意,說明缺少一行說明新組合字串應成為當前組合字串的行,但從意圖來看非常明顯。
我非常不喜歡建議的(隱含的)實作,它需要一個序列,例如:
read
while (check) {
do_stuff
read
}
我更喜歡非重復閱讀:
while (true) {
read
if (!check) break;
do_stuff
}
最后,釋放你的記憶。總是。不要偷懶!
為了完整起見,另一種選擇是存盤組合字串的大小,以避免呼叫strlen您已經知道的內容。您還可以利用calloc和realloc功能,這些功能在很長一段時間內就已經可用:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
size_t capacity = 1;
char *combined = calloc(capacity, 1);
while (true) {
char input1[257];
if (scanf("%6s", input1) != 1 || input1[0] == '#') {
break;
}
capacity = strlen(input1);
combined = realloc(combined, capacity);
strcat(combined, input1);
}
printf("%s", combined);
free(combined);
return 0;
}
最后對于額外的測驗字串:
these are not the droids you're looking for #dummy
a# b## c### d#### e##### #f###### u#######(explicit)
無用的添加
您還可以通過使用一對size/來限制重新分配的數量,capacity并在每次需要更多容量時將容量加倍。此外(這里不是特別有用)檢查記憶體分配函式的回傳值是必須的。我的檢查在realloc這里不必要地復雜,因為記憶體在程式終止時被釋放,但是,盡管如此,釋放你的記憶體。總是。不要偷懶!??
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
size_t capacity = 257, size = 0;
char *combined = calloc(capacity, 1);
if (combined == NULL) {
exit(EXIT_FAILURE);
}
while (true) {
char input1[257];
if (scanf("%6s", input1) != 1 || input1[0] == '#') {
break;
}
size = strlen(input1);
if (size >= capacity) {
char *tmp = realloc(combined, capacity *= 2);
if (tmp == NULL) {
free(combined);
exit(EXIT_FAILURE);
}
combined = tmp;
}
strcat(combined, input1);
}
printf("%s", combined);
free(combined);
return 0;
}
不需要的優化
David C. Rankin 指出了在使用庫函式時需要注意的另一件重要事情,那就是不要假設它們是 O(1)。反復呼叫strcat()并不是最明智的舉動,因為它總是從頭開始掃描。所以在這里我用strcat()更輕的替換了strcpy(),存盤字串的長度,然后添加新的。
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
size_t capacity = 257, size = 0;
char *combined = calloc(capacity, 1);
if (combined == NULL) {
exit(EXIT_FAILURE);
}
while (true) {
char input1[257];
if (scanf("%6s", input1) != 1 || input1[0] == '#') {
break;
}
size_t oldsize = size;
size = strlen(input1);
if (size >= capacity) {
char *tmp = realloc(combined, capacity *= 2);
if (tmp == NULL) {
free(combined);
exit(EXIT_FAILURE);
}
combined = tmp;
}
strcpy(combined oldsize, input1);
}
printf("%s", combined);
free(combined);
return 0;
}
uj5u.com熱心網友回復:
在下面的代碼中,您strcpy()只復制到分配的記憶體的想法是不正確的。strcpy()將復制超出分配的記憶體,這是它不安全的原因,也可能是分段錯誤(核心轉儲)的原因。
strcpy()在您的代碼中將所有字符從復制input1到,combined但由于大小combined小于input1因此問題發生。
相反,您應該使用strncpy()僅復制 n 個字符以避免寫入超出分配空間的記憶體。
您還應該確保combined正確地以 '\0' 結尾。
并且combined[0]='\0'不會用'\0'初始化所有分配的記憶體,這只會將'\0'分配給第一個位元組。要將所有分配的記憶體初始化為 '\0' 您需要使用memset()aftermalloc()
combined = malloc(sizeof(char)*(input1_index 1 1));
combined[0] = '\0'; //use memset() here
strcpy(combined,input1); //Try using strncpy(combined, input1, input1_index) here
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/477691.html
標籤:C
上一篇:通過布林值抽象運算子
下一篇:使用二維陣列計算每個字串中的元音
