-1

スペースで区切られた (符号なし) 整数値を含む文字列を指定すると、文字列内の値の数が得られる関数を作成したいと考えています。

int conta_coords(char *args) {
  char *pal;
  int k=0;
  pal = strtok (args," ");
  while (pal != NULL)
  {
      k++;
      pal =strtok (NULL," ");
  }
  return k;
}

この関数は正しい番号を教えてくれません。誰でも私を助けることができますか?

4

2 に答える 2

1

どのようにして正しい番号が得られないのでしょうか? SSCCE に埋め込まれたコードを次に示します ( Short, Self-Contained, Correct Example )。

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

extern int conta_coords(char *str);

int conta_coords(char *args) {
  char *pal;
  int k=0;
  pal = strtok (args," ");
  while (pal != NULL)
  {
  k++;
      pal =strtok (NULL," ");
  }
  return k;
}

int main(void)
{
    char data[] = "1 23 456 7890 12345";
    printf("Data: %s\n", data);
    printf("Number: %d\n", conta_coords(data));
    printf("Data split: %s\n", data);
    return 0;
}

出力:

$ ./cntnum
Data: 1 23 456 7890 12345
Number: 5
Data split: 1
$ 

それは私には正しいように見えます。ただし、元の文字列はバラバラに切断されていることに注意してください。また、読み取り専用の文字列 (文字列リテラル) を渡した場合、strtok()動作するデータを変更するため、異なる結果が得られた可能性がありますが、文字列リテラルは常に変更可能であるとは限りません (また、試してみるとコア ダンプが発生する可能性があります)。変更する必要があります)。例えば:

    printf("Number: %d\n", conta_coords("   1     23    45   67    99    "));

これにより、「バス エラー」が発生します (無効になっていない場合は、コア ダンプが発生します)。

strspn()これは、非常に過小評価されている C89 標準関数andを使用して、検索された文字列をまったく変更せずに、定数文字列で機能する代替実装ですstrcspn()

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

extern int conta_coords(const char *str);

int conta_coords(const char *str)
{
    const char  digits[] = "0123456789";
    const char *ptr = str;
    int   k = 0;
    int   n = strcspn(ptr, digits);
    while (ptr[n] != '\0')
    {
        ptr += n;
        n = strspn(ptr, digits);
        if (n > 0)
            k++;
        ptr += n;
        n = strcspn(ptr, digits);
    }
    return k;
}

int main(void)
{
    char data[] = "1 23 456 7890 12345";
    printf("Data: %s\n", data);
    printf("Number: %d\n", conta_coords(data));
    printf("Data unsplit: %s\n", data);
    printf("Number: %d\n", conta_coords("   1     23    45   67    99    "));
    return 0;
}

出力:

Data: 1 23 456 7890 12345
Number: 5
Data unsplit: 1 23 456 7890 12345
Number: 5

これに対する 1 つの正当な批判は、整数が空白で区切られていることを要求していないということです (したがって、それをより正確に特徴付けるには、「1 つ以上の連続した数字 (1 つ以上の非数字で区切られている) のシーケンスの数を数えます)」です。指定された文字列に表示されます')。しかし、元のコードも同様の理由で批判される可能性があります。指定された文字列に出現する、1 つまたは複数の空白で区切られた連続した非空白のシーケンスの数をカウントします。実装を改良することはできますが、誤った形式のデータをどのように処理し、問題を報告するかに注意してください。

于 2013-03-24T18:29:59.370 に答える
1

そんな感じ:

#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>

bool is_stringified_num(const char *str, const size_t size)
{
    int n = 0;
    while(n < size && isdigit(str[n++]));

    return n == size;
}

int str_numbers_count(char *str)
{
    int numbers_count = 0;
    char *prev_pos = str;
    char *pos = strchr(str, ' ');

    while(pos)
    {
        if (is_stringified_num(prev_pos, pos - prev_pos)) ++numbers_count ;
        prev_pos = ++pos;
        pos = strchr(pos, ' ');
    }

    if (is_stringified_num(prev_pos, strlen(str) - (prev_pos - str))) ++numbers_count ;

    return numbers_count ;
}

int main(int argc, char *argv[])
{
    char str[] = "1 23 456 7890 12345";
    printf("%s contains %d numbers\n", str, str_numbers_count(str));

    return 0;
}

Ideone は適切にコンパイルされ、次のように出力されます。

1 23 456 7890 12345 contains 5 numbers
于 2013-03-24T18:34:54.540 に答える