试图找到字符串中某些字符的频率,但结果非常接近

时间:2014-06-03 20:23:46

标签: c arrays char frequency

我正在尝试编写一个程序来计算和打印一串DNA的GC内容(通过txt文件输入)。也就是说,一串DNA中G和C的百分比。这是我对GC百分比的函数:

void updateGCCount(char s[], int *gc, int *at) {
   char c[MAXLENGTH];
   int i,GCcount,ATcount;
   float len,GCpercentage;
   GCcount=0;
   ATcount=0;
   for(i=0;c[i]!='\0';++i)
   {
     if(c[i]=='G' || c[i]=='C')
     {
       ++GCcount;
       *gc=GCcount;
     }
     if(c[i]=='A' || c[i]=='T')
     {
       ++ATcount;
       *at=ATcount;
     }
   }
   strcpy(c,s);
   len=strlen(c);
   GCpercentage=*gc/len;
   printf("GC-content: %.2f\n",GCpercentage);

}

这是我的函数定义,应该正确打印GC百分比的部分是我不确定的。下面是我使用输入文本文件的主程序。

#include "genomics.h"

int main(){
   char s[MAXLENGTH];
   int gc, at;
   scanf("%s",s);
   printf("Sequence  : %s\n",s);
   updateGCCount(s, &gc, &at);

   return 0;
}

关于为什么我没有为GCpercentage获得正确值的任何帮助或建议都会很棒。提前谢谢

3 个答案:

答案 0 :(得分:1)

你正在对char数组“c”进行测试:

char c[MAXLENGTH];
...
for(i=0;c[i]!='\0';++i)
{
 if(c[i]=='G' || c[i]=='C')
 {
   ++GCcount;
   *gc=GCcount;
 }
 if(c[i]=='A' || c[i]=='T')
 {
   ++ATcount;
   *at=ATcount;
 }

}

如果应该是s,你传入的数组.c数组可能是超级的,你应该能够从s获得长度

答案 1 :(得分:1)

c未初始化,因此*gc*at根本没有更新,它们包含垃圾..

在这里,您应该使用s代替c

for(i=0;c[i]!='\0';++i)
   {
     if(c[i]=='G' || c[i]=='C')
     {
       ++GCcount;
       *gc=GCcount;
     }
     if(c[i]=='A' || c[i]=='T')
     {
       ++ATcount;
       *at=ATcount;
     }
   }

答案 2 :(得分:0)

这是一个非常不恰当的计划。请考虑以下事项。

#include <stdio.h>
#include <stdlib.h> /* for exit(3) */

float count_gc(const char* s) 
{

您无需通过引用传入的变量传回信息。函数返回值 - 通常是答案&#39;。

您只需扫描参数字符串s的内容,因此无需将其复制到任何地方。

正如其他人所指出的那样,在您复制任何内容之前,您正在扫描数组c[]的内容 - 您正在计算G&#39; G&#39;和&#39; C&#39;在一个(可能是大的)随机内存块中。保持简单可以避免这样的错误。

    int nvalid = 0;
    int gccount = 0;
    float result;

    for (; *s != '\0'; s++) {

虽然你写的for循环不是错误的,但它有些不恰当。在这里,我们检查指针s指向的字符,然后递增指针,直到我们发现自己指向终止字符串的\0。是的,这意味着我们会失去&#39;参数的初始值,但我们在循环后不需要它,所以这并不重要。

        switch (*s) {

这里的开关是一种更自然的结构。您正在查找*s(即指针当前指向的字符)可能具有的一小组可能值。

          case 'G':
          case 'C':
            nvalid++;
            gccount++;
            break;

          case 'A':
          case 'T':
            nvalid++;
            break;

          default:
            /* unexpected character -- ignore it */
            break;

每个 switch语句应该有一个default子句 - 如果没有case,应该始终考虑应该发生的事情条款匹配。在这种情况下,我们只是忽略这个角色。

        }
    }
    if (nvalid == 0) {
        fprintf(stderr, "No valid letters found!\n");
        result = 0.0;
    } else {
        /* Multiply by 1.0 to convert integer gccount to a float */
        result = 1.0*gccount / nvalid;
    }
    return result;

我们将结果返回给调用者,而不是在函数内部打印出来。函数不应该喋喋不休,但要将所有I / O保留在一个地方,通常会将主函数(或更高的函数)保留在其中。

}

int main(int argc, char** argv) 
{
    if (argc != 2) {
        /* Give the user a hint on how to call the program */
        fprintf(stderr, "Usage: gcat <string>\n");
        exit(1);
    }

    printf("Sequence GC-content = %g\n", count_gc(argv[1]));
}

我用以下方式运行:

% cc -o gcat gcat.c
% ./gcat "GCAT ATx foo"         
Sequence GC-content = 0.333333
%

使用C语言,很快就可以轻松打结。总是瞄准简单。