【问题标题】:Need to make a function which returns an int based on which char argument has more uppercase letters需要创建一个函数,该函数根据哪个 char 参数具有更多大写字母返回一个 int
【发布时间】:2015-01-31 00:22:46
【问题描述】:

我正在尝试编写一个函数:

返回:

 0 if the strings have the same number of uppercase letters (A through Z)

-1 if s1 has more uppercase letters than s2

 1 if s2 has more uppercase letters than s1

我最大的问题是字符串在 c 中的处理方式与我在 (java、python) 方面有更多经验的其他语言不同,我也有点困惑何时应该引用指针/取消引用它们.这是我的代码:

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

int more_caps(char * s1, char * s2);

int main(int argc, char **argv){

int result = more_caps(argv[1], argv[2]);
printf("%d %s %s", result, argv[1], argv[2]);
return 0;
}
//EVERYTHING BEFORE THIS MUST NOT BE CHANGED------


int more_caps(char * s1, char *s2){
char * s1caps = strdup(s1);
char * s2caps = strdup(s2);

int *s1counter;
int *s2counter;

int i;
for(i = 0; i < sizeof(s1caps); i++){

    int val1;
    val1 = (int) *s1caps[i];

    if (val1 > 65 && val1 <= 90){
        *s1counter += 1;

    } 
}
for (i = 0; i < sizeof(s2caps); i ++ ){

    int val2;
    val2 = (int) *s2caps[i];
    if (val2 > 65 && val2 <= 90){
        *s2counter += 1;
    }
}

if (*s1counter > *s2counter){
    printf("\n");
    return -1;
}
if (*s1counter < *s2counter){
    printf("\n");
    return 1;
}
else {
    return 0;
}
}

我真的很困惑通过 char 对象进行解析以及我需要如何分配内存或其他东西。通过阅读文档,strdup(char) 为我放入函数中的字符分配了确切的内存 + 1 个字节?无论如何,它要么是段错误,要么是“间接需要指针操作数”。有什么帮助吗?谢谢

【问题讨论】:

  • 您不需要strdup,也不需要任何内存分配。您可以将 s1s2 视为数组,例如for (i=0;s1[i]!='\0';i++) printf("%c\n",s1[i]);
  • 将所有 *s1counter 更改为仅 s1counter。 s2counter 也是如此。您在这里不需要指针,如果您尝试运行此代码,它将核心转储,因为这些指针不指向任何地方。请记住将您的计数器初始化为 0,因为 C 不保证您没有设置自己的任何特定值。正如 user3386109 所说,您不需要 strdup,但如果确实需要它,请记住在完成后释放字符串,否则您将泄漏内存。
  • 谢谢你们。如果您可以定期解析字符,为什么还要为字符分配内存?

标签: c arrays string function


【解决方案1】:

无需复制字符串,也无需使用像65 这样的幻数。使用isupper()向下移动每个字符串,计算大写字母的出现次数

#include <ctype.h>

int more_caps(char * s1, char *s2) {
  unsigned up_count1 = 0;
  // while pointer is not point to the terminating null character ...
  while (*s1) {
    if (isupper(*s1)) up_count1++;
    s1++;
  }

  unsigned up_count2 = 0;
  while (*s2) {
    if (isupper(*s2)) up_count2++;
    s2++;
  }

  // The compare/subtraction is idiomatic in C
  // Each compare returns 0 or 1
  return (up_count2 > up_count1) - (up_count2 < up_count1);
}

为您以后的 C 教育做一些迂腐的改进:

  • 当在 C 中使用索引或数组中的元素计数时,size_t 类型是首选,因为它是索引任何数组的正确大小。 int 类型有时太窄。

     size_t up_count1 = 0;
    
  • is...() 函数采用 int 范围内的值 unsigned charEOF。在这里转换为unsigned char 是有保证的,但我怀疑您的测试用例会暴露非转换用法的弱点。

    if (isupper((unsigned char) *s1)) up_count1++;
    

【讨论】:

    【解决方案2】:
    #include <stdio.h>
    #include <string.h>
    
    int more_caps(char * s1, char * s2);
    
    int main(int argc, char **argv){
    
    int result = more_caps(argv[1], argv[2]);
    printf("%d %s %s", result, argv[1], argv[2]);
    return 0;
    }
    
    int more_caps(char * s1, char *s2){
    //char * s1caps = strdup(s1);
    //char * s2caps = strdup(s2);
    
    int s1counter;
    int s2counter;
    
    s1counter = 0;
    s2counter = 0;
    int i;
    for(i = 0; s1[i] != '\0'; i++){
    
        int val1;
        val1 = (int ) s1[i];
    
        if (val1 > 65 && val1 <= 90){
            s1counter += 1;
    
        } 
    }
    for (i = 0; s2[i] != '\0'; i ++ ){
    
        int val2;
        val2 = (int ) s2[i];
        if (val2 > 65 && val2 <= 90){
            s2counter += 1;
        }
    }
    
    if (s1counter > s2counter){
        printf("\n");
        return -1;
    }
    if (s1counter < s2counter){
        printf("\n");
        return 1;
    }
    else {
        return 0;
    }
    }
    

    固定的功能,似乎工作得很好。谢谢你的帮助。

    【讨论】:

    • 您对大写的检查是残酷和不寻常的。 C 提供了isupper() 函数。
    • 这样好多了。我打算建议if (val1&gt;= 'A' &amp;&amp; val1&lt;= 'Z'),因为使用字符常量可以提高可读性,但@EOF 的建议更好。
    猜你喜欢
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    相关资源
    最近更新 更多