簡體   English   中英

C將字符串拆分為單個單詞,並將單個單詞保存在數組中

[英]C split a string into individual words and save the individual words in an array

因此,假設用戶鍵入“編程一二三”。 我將其保存在userTyped數組中,並將其傳遞給parse()函數。 我需要parse()函數來做到這一點

userargv [0]是程序

userargv [1]是一個

userargv [2]是兩個

等等

我可以告訴它一定是涉及指針的東西,但我無法弄清楚。 代碼如下:

int main(int argc, char **argv)
{
char userTyped[1000];

char* userargv[100];//this is where i need the parse() function to store the arguments to pass to execv

printf("typesomething>");

fgets(userTyped, 1000, stdin);

parse(userTyped, &userargv);

return 0;
}



int parse(char* userTyped, char* userargv){

const char whitespace[2] = " "; //the deliminator
char *strings;

strings = strtok(userTyped, whitespace);

while( strings != NULL )
{
    strings = strtok(NULL, whitespace);

 }
//THIS ALL WORKS, BUT I NEED TO DO SOMETHING LIKE userargv[i] = strings;
//OR *userargv[i] = &strings;
//OR SOMETHING LIKE THAT.

return 0;
}

您必須分配一個字符串數組(char **),並分配其每個元素,然后在其中復制所有找到的字符串;

// nb: the function prototype has been slightly modified 
char** parse(char* userTyped, int *nargs){

    const char whitespace[2] = " "; //the deliminator
    char *strings;
    char **arr;
    int n = 0; // initially no element allocated

    strings = strtok(userTyped, whitespace);

    while( strings != NULL )
    {
        if( n ){ // if there are already allocated elements?
            arr = realloc( arr, ( n + 1 ) * sizeof( char** ) );
        }else{
            arr = malloc( ( n + 1 ) * sizeof( char* ) );
        }

        if( !arr ){
            perror( "parse" );
            exit( -1 );
        }

        // duplicate strings
        arr[ n ] = malloc( strlen( strings )+1 ); 

        if( !arr[ n ] ){
            perror( "parse" );
            exit( -2 );
        }
        strcpy(arr[ n ] , strings); // make a copy of the string

        n++;

        strings = strtok(NULL, whitespace);

    }


    // call freeStrArr when done with arr;
    //
    *nargs  = n; // save array size;
    return arr; // return string array
}

// this how to free the returned array;
void freeStrArr(char ** strarr,int n){
    while( n ){
        n--;
        free( strarr[ n ] );
    }
    free( strarr);
}

當想到需要從parse函數返回的內容時,您將知道要指向包含分配的內存塊的指針數組,該數組包含usertyped中的各個單詞,但是您還需要知道有多少個單獨的單詞。 由於您將指針數組作為參數傳遞給函數本身進行操作,因此僅需要返回給定字符串中單個單詞的數量。 您可以使用以下形式:

int parse (char **words, char *str);

注意:通過傳遞一個指針數組100 ),您只能限制100個單詞,如果超過該數字則沒有機會重新分配。您可以傳遞一個指向char-charger *和如果需要,請重新分配。還請注意,如果您沒有將負數作為錯誤條件返回,則為返回選擇size_t可能更合適)

使用strtok ,可以通過調整strtok使用的分隔符來調整strtok在何處以及如何分隔單詞。 (例如,在句子"This. Not that."如果只是在spaces打斷,則分隔的單詞也將包含'.'字符)。 為防止這種情況,您可以添加'.' strtok使用的分隔符字符串中的字符。 從這個角度來看,將分隔符列表作為參數傳遞給parse函數也很有意義:

int parse (char **words, char *str, char *delims);

您可以使用初始調用以指定的原始字符串作為參數的strtok ,然后在另一個循環中通過傳遞NULL作為參數來解析其余字符串。 或者,您可以在一個for循環中處理這兩種情況。 這只是形式問題,也可以。 一個例子:

int parse (char **words, char *str, char *delims)
{
    int n = 0;
    char *p;

    for (p = strtok (str, delims); p; p = strtok (NULL, delims)) 
    {
        words[n++] = strdup (p);    /* allocate/copy */

        if (n == MAXW) { /* limit reached - realloc/break */
            fprintf (stderr, "warning: MAXW reached.\n");
            break;
        }
    }

    return n;
}

一個簡單的示例程序,它指定分隔符並將它們與數組和字符串一起傳遞給parse函數,可以是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { MAXW = 100, MAXC = 1000 };

int parse (char **words, char *str, char *delims);

int main (void) {

    char usertyped[MAXC] = {0};
    char *userargv[MAXW] = {NULL};
    char *delims = " \t\n.,:;";
    int i, nwords = 0;

    printf ("typesomething> ");

    if (!fgets (usertyped, 1000, stdin)) {
        fprintf (stderr, "error: invalid input.\n");
        return 1;
    }

    if (!(nwords = parse (userargv, usertyped, delims))) {
        fprintf (stderr, "error: parsed no words.\n");
        return 1;
    }

    for (i = 0; i < nwords; i++)
        printf ("userargv[%2d] : %s\n", i, userargv[i]);

    for (i = 0; i < nwords; i++)
        free (userargv[i]);

    return 0;
}

int parse (char **words, char *str, char *delims)
{
    int n = 0;
    char *p;

    for (p = strtok (str, delims); p; p = strtok (NULL, delims)) 
    {
        words[n++] = strdup (p);    /* allocate/copy */

        if (n == MAXW) { /* limit reached - realloc/break */
            fprintf (stderr, "warning: MAXW reached.\n");
            break;
        }
    }

    return n;
}

使用/輸出示例

$ ./bin/strtok_parse
typesomething> a quick brown fox jumps over the laszy dog.
userargv[ 0] : a
userargv[ 1] : quick
userargv[ 2] : brown
userargv[ 3] : fox
userargv[ 4] : jumps
userargv[ 5] : over
userargv[ 6] : the
userargv[ 7] : laszy
userargv[ 8] : dog

幾個額外的筆記。 通常在C語言中,應避免使用camelCase變量。 因此是usertyped而不是上面的userTyped (另一個僅限表單的問題)。 由於strdup為您分配了內存,因此應檢查以確保返回的值不為NULL (與malloccalloc ),以防止內存耗盡。 還要注意,您可以#define SOMECONST value或者如上使用enum定義常量。 如果您還有其他問題,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM