1

As a learning exercise, I am creating a program that converts characters entered through argv[1] to integers. The program then finds the digital mean of the integers.

For example: abc would be 123, and 1+2+3 = 6, six being the digital mean. The first part of the program works, but I am unable to properly code the portion that finds the digital mean.

Output from word abc should be 123 6; instead it is 123 150.


EDIT: Solved!

#include <stdio.h>
#include <strings.h>

int main(int argc, char *argv[])
{
    char stra[27], strb[0];
    int str_num, str_len;
    int final = 0;

    if (argv[1][0] < 'a')
    {
        printf("!Argument missing!");
        return 0;
    }

    strcpy(stra, argv[1]);
    str_len = strlen(stra);

    for (str_num = 0; str_num < str_len; str_num++)
    {
        if (stra[str_num] <= 'z' && stra[str_num] >= 'a')
        {
            strb[str_num] = (stra[str_num] - 'a' + 1) % 9 + '0';
            if (strb[str_num] == '0')
            {
                strb[str_num] = '9';
            }
        }
        else
        {
            printf("%s !Please use only the lower case!", stra);
            return 0;
        }
    }

    for (str_num = 0; str_num < str_len; str_num++)
    {
        final += strb[str_num] - '0';
    }

    printf("%s %i", strb, final);
    return 0;
}
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135

4 Answers4

0

On first inspection, it seems that your program would more or less work if this were

strb[str_num] = (stra[str_num] - 'a') % 9 + 1

Also, strb needs to be 27 characters long as well, not 0; 0-element arrays are rather poor at holding non-zero amounts of data!

You need to check for the argument using argc -- i.e.,

if (argc != 2)
    // complain here

Finally, when you're printing the results, you need to turn the ordinal numbers back into characters. Printing strb as a char* isn't going to give you 123, but rather ^A^B^C, not what you want. So you'll need to print those characters in a loop, adjusting each one by adding the offset of '0' back in.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
0

Seems like you're running past the end of your buffer strb:

char strb[0];
Pubby
  • 51,882
  • 13
  • 139
  • 180
0
strb[str_num] = (stra[str_num] - 'a') % 9 - 207;

The 207 is the largest problem here (aside from your off-by-one error). This line should read:

strb[str_num] = (stra[str_num] - 'a' + 1) % 9;
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
thiton
  • 35,651
  • 4
  • 70
  • 100
  • If I use that, I get smiley face ascii characters instead of integers as output. – salicemspiritus Dec 22 '11 at 21:13
  • ok. if you want to print strb, you need the ascii code the numbers from 1 to 9 : `strb[str_num] = (stra[str_num] - 'a' + 1) % 9 + '0';` – Hicham Dec 22 '11 at 21:23
  • Brilliant! Thank you, it was the + '0' I was missing. This works much better. Now there is only the issue of finding the digital mean. – salicemspiritus Dec 22 '11 at 21:26
0
#include <stdio.h>
#include <strings.h>
int main(int argc, char *argv[])
{
    char *stra;
    char *strb;
    int str_num;
    int str_len;
    int final;
    final = 0;
    if ( (argc >= 2 && argv[1][0] < 'a') || (argc <= 1))
    {
        printf("!Argument missing!");
        return 0;
    }
    str_len = strlen(argv[1]);

    strb = (char*) malloc((str_len+1)*sizeof(char));

    for (str_num = 0; str_num < str_len; str_num++)
    {
        if (argv[1][str_num] <= 'z' && argv[1][str_num] >= 'a')
    {
        strb[str_num] = (argv[1][str_num] - 'a'+1) % 9 + '0'; //to get string with numbers from 1 to 9
        }
        else
        {
            printf("%s !Please use only the lower case!",argv[1]);
            return 0;
        }
    }
    strb[str_len] = '\0' // put the end char of the string : mandatory to print it.
    for (str_num = 0; str_num < str_len; str_num++)
    {
        final += strb[str_num] - '0';  // count the sum of the numbers from 1 to 9 ?
    }
    printf("%s %i",strb,final);
    free(strb);
    return 0;
}
Hicham
  • 983
  • 6
  • 17
  • This is perfect. I do not understand the use of malloc yet, but I have applied portions of your edited code; the program now works with desired output! Thank you very much for your help. – salicemspiritus Dec 22 '11 at 21:44
  • malloc allocate memory : `char* stra = malloc(str_len * sizeof(char))` allocate the memory for a sting of `str_len` (e.g. = 100) character exactly the same as `char stra[100];` do. It is dynamically allocated, the advantge is that you do not have to know the size of the string before compiling... – Hicham Dec 22 '11 at 22:01
  • Thank you! #include takes care of the compiler warning: implicit declaration of malloc. – salicemspiritus Dec 22 '11 at 22:16
  • This answer still needs some work... `malloc` without `free`, "`* sizeof(char)`", checking for char within `'a'` to `'z'` rather than just using `isalpha` or `islower` for ``... – dreamlax Dec 22 '11 at 22:22
  • yes... I added : `free(strb);`. using `islower` is another way to do the check... – Hicham Dec 22 '11 at 22:40
  • There's absolutely no need to cast the result of `malloc` to `char *` because in C, an implicit cast from `void *` is allowed. This can mask a more serious error if the header that declares `malloc` is not included, because the C implementation is allowed to assume that the function returns `int`, which you cast to `char *` (which may have different sizes and the conversion is implementation-defined anyway). Also, `sizeof(char)` is defined by the C standard to be 1, so it is redundant. – dreamlax Dec 22 '11 at 22:42
  • The headers that you have included do not actually declare `malloc` (because it is declared in `stdlib.h`). – dreamlax Dec 22 '11 at 22:44
  • @eharvest: If I am wrong, please point me to the relevant part of the C89 specification that disproves me, because I can reference several parts of this specification to prove me right. – dreamlax Dec 22 '11 at 22:53
  • my vc++ compiler does not accept the `malloc` without the cast... `sizeof(char)` is for the clarity of the code, to have all the malloc with the same structure. – Hicham Dec 22 '11 at 23:34
  • @eharvest. ***C++ IS NOT C***, you CANNOT compile all C code with a C++ compiler. C++ **DOES NOT** allow implicit conversion from `void *`, so in C++ you *need* a cast, however this question is tagged `c`, not `c++`. Also `sizeof(char)` will **NEVER** be anything except 1. That is how it is defined in the C standard. Why not multiply everything by 1? `if (argc < 1 * 1 * 1 * 1)`, or `int i = 0 * 1;`. It is redundant and unnecessary. – dreamlax Dec 23 '11 at 00:33
  • In C (**NOT C++**), if you explicitly cast the result of `malloc`, you are masking a *potential compiler warning* that may result in *undefined or implementationed-defined behaviour*. That is a **FACT**. Whether you chose to cast the result in C is personal choice, but I've just proven to you that it is disadvantageous to do so. – dreamlax Dec 23 '11 at 00:34
  • In C++ you should not be using `malloc` anyway, you should be using `new`/`new[]` and `delete`/`delete[]` instead. – dreamlax Dec 23 '11 at 00:35
  • i use vc++ compiler ! but i write c (and c++) programs and till now, it works fine. you are masking only other potential errors(include problem) by the cast. if no error away, no problem. the sizeof helps to have a consistent code !!!! i said it a lot of times !!! – Hicham Dec 23 '11 at 01:20
  • im not talking about c++ but about c. new and delete does not interest me !! – Hicham Dec 23 '11 at 01:25
  • @eharvest: You are talking about C++ because you said you couldn't compile the code with vc++. vc++ is **A C++ COMPILER** therefore C++ rules apply. I am not alone on this, see [here](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – dreamlax Dec 23 '11 at 04:08
  • im talking about c code compiled by vc++ which is c++ compiler. it is not an error to cast malloc but not doing it make the code non working in vc++. – Hicham Dec 23 '11 at 04:22