主頁 > 移動端開發 > 如何在C中重復讀取和連接字串

如何在C中重復讀取和連接字串

2022-05-19 18:13:50 移動端開發

程式需要做到以下幾點:

  1. 初始化組合字串變數。
  2. 讀取一個不超過 256 個字符的字串 (input1) 然后:直到讀取的字串的第一個字符為 '#'
  3. 為新的組合字串變數分配足夠的空間來保存當前組合字串變數和新的讀取字串 (input1)。
  4. 然后將舊組合變數的內容復制到新的、更大的組合變數字串中。
  5. 然后將新讀取的字串 (input1) 連接到新組合字串的末尾。
  6. 釋放舊的組合字串。
  7. 再次將字串讀入輸入 1。
  8. 在用戶鍵入帶有“#”的字串后,列印出新的組合字串。

測驗輸入:我在哪里#這里

預期輸出: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您已經知道的內容。您還可以利用callocrealloc功能,這些功能在很長一段時間內就已經可用:

#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

上一篇:通過布林值抽象運算子

下一篇:使用二維陣列計算每個字串中的元音

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more