在给定的两个字符串

时间:2017-06-24 08:59:06

标签: c string char malloc

我遇到了一个问题,我们需要在给定的两个字符串中找到常用词。问题的描述:

  

概述:给定两个字符串,找到两个字符串共有的字。   例如:输入:"一二三","二三五"。输出:"两个","三个"。

     

INPUTS:两个字符串。

     

OUTPUT:两个给定字符串中的常用字,返回字符串的2D数组。

     

错误案例:对无效输入返回NULL。

     

注意:如果没有常用词,则返回NULL。

我已经解决了这个问题,并开始在Visual Studio 2013中解决它。 它有很多测试用例。

这是我的代码:

int ispresent(char*a, char *b)
{
    int m = strlen(a);
    int n = strlen(b);
    int i, j;
    for ( i = 0; i <= n - m; i++){             
        for ( j = 0; j<m; j++){
            if (a[j] != b[i + j]) break;
        }
        if (j == m)
            return 1;
   }
    return 0;
}
char ** commonWords(char *str1, char *str2)
{
    if (str1 != NULL&&str2 != NULL)
    {
        char **res = (char**)malloc(10 * sizeof(char*));
        for (int i = 0; i < 10; i++)
            res[i] = (char*)malloc(31 * sizeof(char));
        char *a = (char*)malloc(31 * sizeof(char));
        int k = 0, j = 0;
        for (int i = 0; str1[i] != '\0'; i++, j++)
        {
            if (str1[i] != ' ')
                a[j] = str1[i];
            if (str1[i] == ' ' || str1[i] == '\0')
            {
                a[j] = '\0';
                if (ispresent(a, str2))
                    res[k++] = a;
                j = 0;
            }
        }
        return res;
    }
    return NULL;
}

但我在这里遇到运行时错误: 该程序意外终止

我可以获得任何解决方案吗?

我有一个建议,它可能是重复的  但我的代码与此不一样..我不是在问这个问题&gt;我问我的代码建议

3 个答案:

答案 0 :(得分:1)

最后,我得到的解决方案几乎没有变化。并感谢为此做出贡献的人们。 这个解决方案适用于我的所有测试用例:

解决方案:

 #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define SIZE 10
    #define WORD_SIZE 31 
    int ispresent(char*a, char *b)
    {
        int m = strlen(a);
        int n = strlen(b);
        int i, j;
        for (i = 0; i <= n - m; i++){
            for (j = 0; j<m; j++){
                if (a[j] != b[i + j]) break;
            }
            if (j == m)
                return 1;
        }
        return 0;
    }
    char ** commonWords(char *str1, char *str2)
    {
        if (str1 != NULL&&str2 != NULL)
        {
            char **res = (char**)malloc(SIZE * sizeof(char*));
            for (int p = 0; p < 3; p++)
                res[p] = (char*)malloc(WORD_SIZE * sizeof(char));
            char *a = (char*)malloc(WORD_SIZE * sizeof(char));
            int k = 0, j = 0;
            for (int i = 0; str1[i] != '\0'; i++)
            {
                if (str1[i] != ' ')
                    a[j++] = str1[i];
                if (str1[i] == ' ' || str1[i] == '\0')
                {
                    a[j++] = '\0';
                    if (ispresent(a, str2)&&a!="\0")
                        res[k++] = strdup(a);
                    j = 0;
                }
            }
            for (int x = 0; x <=k; x++)
                if (res[x] == "\0"||k==0||strlen(res[x])<=1)
                    return NULL;
            return res;
        }
        return NULL;
    }

我在Visual Studio中运行的程序的测试用例是

test.spec file:

#include "stdafx.h"
#include "CppUnitTest.h"
#include "../src/commonWords.cpp"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace spec
{
    TEST_CLASS(commonWordsSpec)
    {
    public:

        bool strcmp(char *str1, char *str2) {
            while (*str1 && *str2) {
                if (*str1 != *str2) {
                    return false;
                }
                str1++;
                str2++;
            }
            return !*str1 && !*str2;
        }

        bool compare(char expected[][31], int count, char **actual) {
            for (int i = 0; i < count; ++i) {
                bool found = false;
                for (int j = 0; j < count; ++j) {
                    if (strcmp(expected[i], actual[j])) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    return false;
                }
            }
            return true;
        }

        TEST_METHOD(nullInput)
        {
            Assert::IsNull(commonWords(NULL, NULL), L"Common Words null 
       check failed.", LINE_INFO());
        }

        TEST_METHOD(stringsWithSpaces)
        {
            char *str1 = "       ";
            char *str2 = " who what";
            Assert::IsNull(commonWords(str1, str2), L"No common words check failed.", LINE_INFO());
        }

        TEST_METHOD(noCommonWordsInput)
        {
            char *str1 = "the are all is well";
            char *str2 = " who what";
            Assert::IsNull(commonWords(str1, str2), L"No common words check failed.", LINE_INFO());
        }

        TEST_METHOD(commonWordsInput)
        {
            char *str1 = "the are all is well";
            char *str2 = "is who the";
            char expected[2][31] = { { "the" }, { "is" } };
            char **res = commonWords(str1, str2);
            Assert::IsTrue(compare(expected, 2, res), L"Common Words positive check failed.", LINE_INFO());
        }

    };
}

答案 1 :(得分:0)

我认为通过这个练习你应该学习这些东西:

  1. 不要使用魔术数字,而是使用#define
  2. 如果函数可以返回NULL
  3. ,则始终检查指针是否为NULL
  4. 检查边界,确保输入过长时代码的行为合理
  5. 不要忘记你分配的空闲记忆
  6. 尽可能使用库函数
  7. 这是一个如何完成的例子。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAX_WORD_LEN    30
    #define MAX_WORDS       10
    
    
    char ** commonWords(char *str1, char *str2)
    {
    if (str1 != NULL && str2 != NULL)
    {
        char a[MAX_WORD_LEN+1];
        char **res = (char**)calloc(MAX_WORDS+1, sizeof(char*));
        if(!res) return NULL;
    
        int k = 0, j = 0;
        for (int i = 0; str1[i] != '\0' && k < MAX_WORDS; i++)
        {
            if (str1[i] != ' ' && j < MAX_WORD_LEN)
                a[j++] = str1[i];
            if (str1[i] == ' ' || str1[i] == '\0') {
                a[j] = '\0';
                if (strstr(str2,a)) {
                    res[k++] = strdup(a);
                }
                j = 0;
            }
        }
        return res;
    }
    return NULL;
    }
    
    int main(void)
    {
    char **cw = commonWords("one two three", "two three five");
    if(cw) {
        for(int i=0; cw[i]; i++) {
            printf("%s ",cw[i]);
            free(cw[i]);
        }
        free(cw);
    }
    printf("\n");
    return 0;
    }
    

    请记住,只有练习才能学习;)

答案 2 :(得分:0)

继续我的评论,一种简单而合理的方法就是使用loggedInUser(或您喜欢的任何方法)标记化第一个字符串中的单词。为找到的每个单词分配存储空间并将单词存储在临时strtok变量中。 标记化第二个字符串,并将第一个字符串中的每个单词与第二个字符串中的每个标记进行比较。如果它们匹配,则将指向第一个数组中的单词的指针添加为char **tmp数组中的指针。 (您不需要分配额外的存储空间,因为您的所有results变量都将保留指向char **results中已分配的内存的指针。(在完成使用之前,不要释放tmp { {1}})

由于你知道有多少比较导致匹配,因此输出tmp中的每个单词都很简单。

要将所有部分组合在一起,您可以执行以下操作:

result

注意: result修改作为参数传递的字符串,因此使用复合文字来确保#include <stdio.h> #include <stdlib.h> #include <string.h> enum { NPT = 10, MAXC = 32 }; int main (int argc, char **argv) { char *s1 = argc > 1 ? argv[1] : (char[]) { "My dog has fleas and my cat has none." }, *s2 = argc > 2 ? argv[2] : (char[]) { "My frog likes the dog and the rat like the cat. "}, *delim = " \t\n.,", **result = malloc (NPT * sizeof *result), **tmp = malloc (NPT * sizeof *tmp); int n = 0, r = 0; if (!result || !tmp) { /*... handle mem error ...*/ } printf ("finding common words between:\n s1: %s\n s2: %s\n", s1, s2); /* tokenize all words in s1, save in tmp */ for (char *p = strtok (s1, delim); p && n < NPT; p = strtok (NULL, delim)) tmp[n++] = strdup (p); /* tokenize all words in s2, compare against words in tmp, save result */ for (char *p = strtok (s2, delim); p && r < n; p = strtok (NULL, delim)) { for (int i = 0; i < n; i++) if (strcmp (p, tmp[i]) == 0) result[r++] = tmp[i]; } if (r) printf ("\ncommon words:\n"); else printf ("\nno common words.\n"); for (int i = 0; i < r; i++) printf (" %s\n", result[i]); free (result); /* free all allocated memory */ for (int i = 0; i < n; i++) free (tmp[i]); free (tmp); return 0; } strtok字符数组能够修改

示例使用/输出

s1

不存在常用词的示例。

s2

仔细看看,如果您有任何其他问题,请告诉我。