我的程序的目的是测试字符串中最长的单词,并返回最长的单词是否与预期结果匹配。
我写了代码,但是我的大脑被困在了一个地方,我要把我函数中最长的一行字的结果存储到char数组结果中。你怎么用C语言写的?
我的努力:

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

static int testsExecuted = 0;
static int testsFailed = 0;

char testLongestWord(char line[], char expected[]);
void longestWord(char line[]);

int main(int args, char *argv[]){
    printf("%s\n", "Testing typical cases, including punctuation\n");
    testLongestWord("the quick brown foxes jumped over the lazy dogs", "jumped");
    testLongestWord("hello world she said", "hello");
    testLongestWord("Hello\tworld\tshe\tsaid", "Hello");
    testLongestWord("HELLO, world she said", "HELLO");
    testLongestWord("hello world! she said???", "hello");
    testLongestWord("\"hello world!\", she said.", "hello");
    testLongestWord("easy as abc123", "abc123");
    testLongestWord("easy as abc,123", "easy");


    printf("\n%s\n", "Testing empty cases\n" );
    testLongestWord("", "");
    testLongestWord("!", "");
    testLongestWord(" ", "");
    testLongestWord("\t", "");
    testLongestWord("      ", "");
    testLongestWord("# $ ? % !", "");

    printf("\n%s\n", "Testing edge cases\n" );
    testLongestWord("a", "a");
    testLongestWord("abc", "abc");
    testLongestWord("abc d e f ghi", "abc");
    testLongestWord("a a b cc dd abc", "abc");
    testLongestWord("\"a a b cc dd abc.\"", "abc");


    printf("\n%s\n", "Testing apostrophes and dashes\n" );
    testLongestWord("this isn't five chars", "chars");
    testLongestWord("this should've been eight chars said the computer", "should've");
    testLongestWord("'this should've been eight chars', said the computer", "should've");
    testLongestWord("'hello world!', she said softly.", "softly");
    testLongestWord("topsy-turvy is a tenletter word", "topsy-turvy");
    testLongestWord("topsy-turvy should not be incorrectly eleven characters", "incorrectly");
    testLongestWord("---in-between-these---", "in-between-these");
    testLongestWord("---in---between---these---", "between");
    testLongestWord("here-is-an-edge-case but a muchmuchlongerword", "muchmuchlongerword");
    testLongestWord("d-o-n't-g-o-o-v-e-r-t-h-e-e-d-g-e with muchmuchlongerwords", "muchmuchlongerwords");
    testLongestWord("two=five-3 isn't three", "three");

    printf("\n%s\n", "These tests will be opposite in the C version\n");
    testLongestWord("the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.", "Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch");
    testLongestWord("the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.", "antidisestablishment");
    testLongestWord("Java strings may contain \0 in the interior", "interior");
    testLongestWord("C strings cannot contain \0 in the interior", "strings");

    printf("Total number of test executed:  %d\n", testsExecuted );
    printf("number of test passed:  %d\n", (testsExecuted - testsFailed));
    printf("Number of test failed: %d\n", testsFailed );

    //longestWord("Java strings may contain \0 in the interior");

}

char testLongestWord(char line[], char expected[]){
    //char result[200];
      String result = longestWords(line); //This is how it'd have been in Java
    /*longestWord(line);*/
    //strcpy(result, line);
    //char *result = longestWord(line);
    //printf("%s\n", line );
    //longestWord(&line)

    if(strcmp(result,expected)){ // function returns 0 if they are equal
        printf("passed: '%s' from '%s'\n", result, line);
    }else{
        printf("FAILED: '%s' from '%s'\n", expected, result);
        testsFailed++;
    }
    testsExecuted++;
    return 0;

}


void longestWord(char line[]){
    char longest[200];

    int pos = 0;
    int longestLength = 0;
    char current[300];
    int currentLength = 0;
    char ch;
    size_t maxPos = strlen(line);

    while(pos < maxPos){
        ch = line[pos++];
        for(pos = 0; pos < maxPos;pos++){
            ch = line[pos++];
            if((ch == '\'' || ch == '-') && (pos > 0) && isalpha(line[pos-1]) && isalpha(line[pos+1])){
                strcpy(current, &ch);
            }else if(isalpha(ch) || isdigit(ch)){
                strcpy(current, &ch);
                currentLength++;
                //printf("%s\n", longest );

            }else{
                if(currentLength > longestLength){
                    strcpy(longest,current);
                    longestLength = currentLength;
                }
                //strcpy(current, "");
                currentLength =0;
            }
        }

    }

}

输出:(这个输出是在一个类似的Java代码中给出的)
Testing typical cases, including punctuation

Passed: 'jumped' from 'the quick brown foxes jumped over the lazy dogs'
Passed: 'hello' from 'hello world she said'
Passed: 'Hello' from 'Hello world   she said'
Passed: 'HELLO' from 'HELLO, world she said'
Passed: 'hello' from 'hello world! she said???'
Passed: 'hello' from '"hello world!", she said.'
Passed: 'abc123' from 'easy as abc123'
Passed: 'easy' from 'easy as abc,123'

Testing empty cases

Passed: '' from ''
Passed: '' from '!'
Passed: '' from ' '
Passed: '' from '   '
Passed: '' from '      '
Passed: '' from '# $ ? % !'

Testing edge cases

Passed: 'a' from 'a'
Passed: 'abc' from 'abc'
Passed: 'abc' from 'abc d e f ghi'
Passed: 'abc' from 'a a b cc dd abc'
Passed: 'abc' from '"a a b cc dd abc."'

Testing apostrophes and dashes

Passed: 'chars' from 'this isn't five chars'
Passed: 'should've' from 'this should've been eight chars said the computer'
Passed: 'should've' from ''this should've been eight chars', said the computer'
Passed: 'softly' from ''hello world!', she said softly.'
Passed: 'topsy-turvy' from 'topsy-turvy is a tenletter word'
Passed: 'incorrectly' from 'topsy-turvy should not be incorrectly eleven characters'
Passed: 'in-between-these' from '---in-between-these---'
Passed: 'between' from '---in---between---these---'
Passed: 'muchmuchlongerword' from 'here-is-an-edge-case but a muchmuchlongerword'
Passed: 'muchmuchlongerwords' from 'd-o-n't-g-o-o-v-e-r-t-h-e-e-d-g-e with muchmuchlongerwords'
Passed: 'three' from 'two=five-3 isn't three'

These tests will be opposite in the C version

Passed: 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch' from 'the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.'
FAILED: 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch' instead of 'antidisestablishment' from 'the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.'
Passed: 'interior' from 'Java strings may contain  in the interior'
FAILED: 'interior' instead of 'strings' from 'C strings cannot contain  in the interior'

Total number of tests executed: 34
Number of tests passed:         32
Number of tests failed:         2

最佳答案

你的代码有一些问题。你最后的感觉被颠倒了。找词逻辑有点复杂,多次前进,返回字符串的机制(ala java)不起作用。一种简化方法是将一些strcmp代码分割成pos
我已经用一些注释修复了代码[请原谅不必要的样式清理]:

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

static int testsExecuted = 0;
static int testsFailed = 0;

char testLongestWord(char line[], char expected[]);
//void longestWord(char line[]);

int
main(int args, char *argv[])
{
    printf("%s\n", "Testing typical cases, including punctuation\n");
    testLongestWord("the quick brown foxes jumped over the lazy dogs", "jumped");
    testLongestWord("hello world she said", "hello");
    testLongestWord("Hello\tworld\tshe\tsaid", "Hello");
    testLongestWord("HELLO, world she said", "HELLO");
    testLongestWord("hello world! she said???", "hello");
    testLongestWord("\"hello world!\", she said.", "hello");
    testLongestWord("easy as abc123", "abc123");
    testLongestWord("easy as abc,123", "easy");

    printf("\n%s\n", "Testing empty cases\n");
    testLongestWord("", "");
    testLongestWord("!", "");
    testLongestWord(" ", "");
    testLongestWord("\t", "");
    testLongestWord("      ", "");
    testLongestWord("# $ ? % !", "");

    printf("\n%s\n", "Testing edge cases\n");
    testLongestWord("a", "a");
    testLongestWord("abc", "abc");
    testLongestWord("abc d e f ghi", "abc");
    testLongestWord("a a b cc dd abc", "abc");
    testLongestWord("\"a a b cc dd abc.\"", "abc");

    printf("\n%s\n", "Testing apostrophes and dashes\n");
    testLongestWord("this isn't five chars", "chars");
    testLongestWord("this should've been eight chars said the computer", "should've");
    testLongestWord("'this should've been eight chars', said the computer", "should've");
    testLongestWord("'hello world!', she said softly.", "softly");
    testLongestWord("topsy-turvy is a tenletter word", "topsy-turvy");
    testLongestWord("topsy-turvy should not be incorrectly eleven characters", "incorrectly");
    testLongestWord("---in-between-these---", "in-between-these");
    testLongestWord("---in---between---these---", "between");
    testLongestWord("here-is-an-edge-case but a muchmuchlongerword", "muchmuchlongerword");
    testLongestWord("d-o-n't-g-o-o-v-e-r-t-h-e-e-d-g-e with muchmuchlongerwords", "muchmuchlongerwords");
    testLongestWord("two=five-3 isn't three", "three");

    printf("\n%s\n", "These tests will be opposite in the C version\n");
    testLongestWord("the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.", "Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch");
    testLongestWord("the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.", "antidisestablishment");
    testLongestWord("Java strings may contain \0 in the interior", "interior");
    testLongestWord("C strings cannot contain \0 in the interior", "strings");

    printf("Total number of test executed:  %d\n", testsExecuted);
    printf("number of test passed:  %d\n", (testsExecuted - testsFailed));
    printf("Number of test failed: %d\n", testsFailed);

    // longestWord("Java strings may contain \0 in the interior");

}

// nextWord -- get next word
char *
nextWord(char *word,char *line)
{
    char *lhs;
    int c2;
    int alfcnt;
    int alf1;
    int alf2;
    int ch;

    //printf("nextWord: ENTER line='%s'\n",line);

    alfcnt = 0;
    lhs = word;

    for (ch = *line;  ch != 0;  ch = *++line) {
        alf1 = isalpha(ch) || isdigit(ch);

        // store word chars
        if (alf1) {
            *lhs++ = ch;
            alfcnt = 1;
            continue;
        }

        if (alfcnt) {
            c2 = line[1];
            alf2 = isalpha(c2) || isdigit(c2);

            if (alf2) {
                switch (ch) {
                case '\'': // store single quote [if it's part of a contraction]
                    *lhs++ = ch;
                    continue;
                    break;

                case '-': // store hyphen
                    *lhs++ = ch;
                    continue;
                    break;
                }
            }

            // didn't get a word char -- stop because we're at the end of a word
            break;
        }
    }

    *lhs = 0;

    if (! alfcnt)
        line = NULL;

    //printf("nextWord: EXIT lhs='%s' line='%s'\n",lhs,line);

    return line;
}

void
longestWord(char *longest,char *line)
{
    int longestLength = 0;
    char current[300];
    int currentLength = 0;
    char *cp;

    longest[0] = 0;

    while (1) {
        // get next word in line [we advance the line pointer for next round]
        line = nextWord(current,line);
        if (line == NULL)
            break;

        // get string length -- punctuation is _not_ counted in string length
        currentLength = 0;
        for (cp = current;  *cp != 0;  ++cp) {
            switch (*cp) {
            case '-':
            case '\'':
                break;
            default:
                currentLength += 1;
                break;
            }
        }

        // store longer word
        if (currentLength > longestLength) {
            strcpy(longest,current);
            longestLength = currentLength;
            continue;
        }

        if (currentLength < longestLength)
            continue;

        cp = strchr(longest,'-');
        if (cp == NULL)
            continue;

        cp = strchr(current,'-');
        if (cp != NULL)
            continue;

        // prefer non-dash over dash
        strcpy(longest,current);
    }
}

char
testLongestWord(char *line,char *expected)
{
    char result[2000];
    //char result = longestWords(line); // This is how it'd have been in Java

    longestWord(result,line);

    /* longestWord(line); */
    // strcpy(result, line);
    // char *result = longestWord(line);
    // printf("%s\n", line );
    // longestWord(&line)

    // function returns 0 if they are equal
    // NOTE/BUG: the sense of the if was wrong
    if (strcmp(result, expected) == 0) {
        printf("passed: '%s' from '%s'\n", result, line);
    }
    else {
        printf("FAILED: got '%s' from '%s' -- expected '%s'\n",
            result, line, expected);
        testsFailed++;
    }

    testsExecuted++;

    return 0;
}

更新:
根据您的请求,下面是一个完全注释的版本,解释变量定义并注释控制流。
当我这么做的时候,我意识到longestWord是在计算那些需要重新计算的东西,仅仅因为nextWord没有办法传达这些信息。
所以,我添加了一个nextWord结构,它允许longestWord传回多个值。我不知道这是否在java中完成,但在C中相当常见。
返回多个值的另一种方法是执行以下操作:
nextWord(blah,&var1,&var2,&var3,...);

这很快就变得笨拙起来,所以我决定选择更干净的方法,即使一开始理解起来稍微有点困难。
实际上,另一种思考方法是nextWord就像一个[java]类,只有一个方法nextword。在这种情况下,我可能会颠倒nextWord参数(例如nextword)的顺序,因为我在C中的约定是对象实例指针是第一个参数。
#include <stdio.h>
#include <ctype.h>
#include <string.h>

static int testsExecuted = 0;
static int testsFailed = 0;

char testLongestWord(char line[],char expected[]);

//void longestWord(char line[]);

int
main(int args,char *argv[])
{
    printf("%s\n", "Testing typical cases, including punctuation\n");
    testLongestWord("the quick brown foxes jumped over the lazy dogs", "jumped");
    testLongestWord("hello world she said", "hello");
    testLongestWord("Hello\tworld\tshe\tsaid", "Hello");
    testLongestWord("HELLO, world she said", "HELLO");
    testLongestWord("hello world! she said???", "hello");
    testLongestWord("\"hello world!\", she said.", "hello");
    testLongestWord("easy as abc123", "abc123");
    testLongestWord("easy as abc,123", "easy");

    printf("\n%s\n", "Testing empty cases\n");
    testLongestWord("", "");
    testLongestWord("!", "");
    testLongestWord(" ", "");
    testLongestWord("\t", "");
    testLongestWord("      ", "");
    testLongestWord("# $ ? % !", "");

    printf("\n%s\n", "Testing edge cases\n");
    testLongestWord("a", "a");
    testLongestWord("abc", "abc");
    testLongestWord("abc d e f ghi", "abc");
    testLongestWord("a a b cc dd abc", "abc");
    testLongestWord("\"a a b cc dd abc.\"", "abc");

    printf("\n%s\n", "Testing apostrophes and dashes\n");
    testLongestWord("this isn't five chars", "chars");
    testLongestWord("this should've been eight chars said the computer", "should've");
    testLongestWord("'this should've been eight chars', said the computer", "should've");
    testLongestWord("'hello world!', she said softly.", "softly");
    testLongestWord("topsy-turvy is a tenletter word", "topsy-turvy");
    testLongestWord("topsy-turvy should not be incorrectly eleven characters", "incorrectly");
    testLongestWord("---in-between-these---", "in-between-these");
    testLongestWord("---in---between---these---", "between");
    testLongestWord("here-is-an-edge-case but a muchmuchlongerword", "muchmuchlongerword");
    testLongestWord("d-o-n't-g-o-o-v-e-r-t-h-e-e-d-g-e with muchmuchlongerwords", "muchmuchlongerwords");
    testLongestWord("two=five-3 isn't three", "three");

    printf("\n%s\n", "These tests will be opposite in the C version\n");
    testLongestWord("the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.", "Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch");
    testLongestWord("the word antidisestablishmentarianism is very long but not as long as 'Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch'.", "antidisestablishment");
    testLongestWord("Java strings may contain \0 in the interior", "interior");
    testLongestWord("C strings cannot contain \0 in the interior", "strings");

    printf("Total number of test executed:  %d\n", testsExecuted);
    printf("number of test passed:  %d\n", (testsExecuted - testsFailed));
    printf("Number of test failed: %d\n", testsFailed);

    // longestWord("Java strings may contain \0 in the interior");

}

// nextWord state control ("helper")
// NOTE: we use this sort of struct when we must maintain/update _multiple_
// variables across a function call [or calls]
struct nextword {
    char *line;                         // current line position [updated]
    int alfcnt;                         // alphanumeric length
    int hypflg;                         // 1=word is hyphenated
};

// nextWord -- get next word
void
nextWord(char *word,struct nextword *rtn)
// word -- pointer to place to store extracted word
// rtn -- pointer to our state control and values we return
{
    char *line;  // pointer to sentence/phrase to extract words from
    char *wp;  // current position in word
    int ch;  // current character
    int c2;  // next character [lookahead if needed]
    int alf1;  // 1=current char is alphanumeric
    int alf2;  // 1=next char is alphanumeric
    int alfcnt;  // number of alphanumeric characters

    // printf("nextWord: ENTER line='%s'\n",line);

    // say no alpha chars and "not hyphenated"
    alfcnt = 0;
    rtn->hypflg = 0;

    // set the word "creeper" [current position for destination]
    // NOTES:
    // (1) using a separate "wp" in unnecessary as we don't need to retain the
    //     original word value (i.e. below we could just do "word" in place of
    //     "wp")
    // (2) in the previous version, this was called "lhs" [which, as you
    //     surmised, meant "left hand side"]
    // (3) in my style, this might also be called "dst" [for destination]
    wp = word;

    // get "source" pointer
    // NOTES:
    // (1) in my style, this could also be named "rhs" ["right hand side"]
    // (2) another style would be "src" for "source" if we used "dst" above
    line = rtn->line;

    for (ch = *line;  ch != 0;  ch = *++line) {
        // is current char alphanumeric?
        alf1 = isalpha(ch) || isdigit(ch);

        // store word chars
        // NOTE: only these characters are considered for our purposes of
        // "string" length
        if (alf1) {
            *wp++ = ch;
            alfcnt += 1;
            continue;
        }

        // iff we've started a word, we consider internal punctuation and
        // hyphenation
        if (alfcnt) {
            // peek at _next_ character in line
            c2 = line[1];
            alf2 = isalpha(c2) || isdigit(c2);

            // consider special characters if _next_ character is alpha
            if (alf2) {
                switch (ch) {
                case '\'':  // store quote [if it's part of a contraction]
                    *wp++ = ch;
                    continue;
                    break;

                case '-':  // store hyphen
                    *wp++ = ch;
                    rtn->hypflg = 1;  // remember that word is hyphenated
                    continue;
                    break;
                }
            }

            // didn't get a word char -- stop because we're at the end of a word
            break;
        }

        // wait for start of a word (i.e. alphanumeric)
    }

    // finish off the extracted word
    *wp = 0;

    // if we didn't find any word chars, tell caller to stop
    if (! alfcnt)
        line = NULL;

    // return multiple values to caller
    // NOTE: we already updated hypflg above [if necessary]
    rtn->alfcnt = alfcnt;
    rtn->line = line;

    // printf("nextWord: EXIT lhs='%s' line='%s'\n",lhs,line);
}

// longestWord -- find longest word in a line
void
longestWord(char *longest,char *line)
// longest -- pointer to buffer where we return the longest extracted word
// line -- pointer to string that has the phrase to extract words from
{
    int longlen = 0;  // length of longest string so far
    int longhyp = 0;  // 1=longest word is hyphenated
    char current[300];  // current word being considered
    int curlen;
    struct nextword rtn;  // control struct to allow nextWord to update state

    // handle empty strings
    longest[0] = 0;

    // initialize this once -- nextWord will update it
    rtn.line = line;

    while (1) {
        // get next word in line [we advance the line pointer for next round]
        nextWord(current,&rtn);

        // no more words found
        if (rtn.line == NULL)
            break;

        // nextWord has already computed the length for us
        curlen = rtn.alfcnt;

        // store longer word [remembering its length and whether it's
        // hyphenated or not]
        if (curlen > longlen) {
            strcpy(longest,current);
            longlen = curlen;
            longhyp = rtn.hypflg;
            continue;
        }

        // skip shorter words than what we already have
        if (curlen < longlen)
            continue;

        // decide if longest is hyphenated -- ignore if not
        if (! longhyp)
            continue;

        // decide if current is hyphenated -- ignore if so (i.e. it's no better)
        if (rtn.hypflg)
            continue;

        // prefer non-dash over dash
        strcpy(longest,current);
        longhyp = rtn.hypflg;
    }
}

char
testLongestWord(char *line,char *expected)
{
    char result[2000];

    // char result = longestWords(line); // This is how it'd have been in Java

    longestWord(result,line);

    /* longestWord(line); */
    // strcpy(result,line);
    // char *result = longestWord(line);
    // printf("%s\n",line );
    // longestWord(&line)

    // function returns 0 if they are equal
    // NOTE/BUG: the sense of the if was wrong
    if (strcmp(result,expected) == 0) {
        printf("passed: '%s' from '%s'\n",result,line);
    }
    else {
        printf("FAILED: got '%s' from '%s' -- expected '%s'\n",
            result,line,expected);
        testsFailed++;
    }

    testsExecuted++;

    return 0;
}

关于c - 如何将从函数获得的结果转移到C中的char数组?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35165509/

10-10 21:16