3

I'm trying to write a C program that goes through a string of characters, and prints out "NON-LETTER" if the given argument through the command line.

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

int main(int argc, char **argv)
{
    int i = 0;
    for (i = 1; i < argc; i++){
        if (!isalpha(argv[i])){
            printf("NON-LETTER\n");
        }
    }

    return 0;
}

But I'm getting a segmentation fault. Is this because of the comparison I'm making with isalpha()? It looks like argv[i] is a string?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
econCodergirl
  • 315
  • 1
  • 3
  • 8

3 Answers3

2

argv[i] is a char * pointing to the i-th argument (a string), while isalpha expects a single character expressed as an int1.

What happens here is that you are passing a pointer, it gets implicitly converted to int, isalpha tries to interpret it as a character (probably as an index in a lookup table) and everything explodes (technically, it's undefined behavior).

What you probably wanted to do was to check each argument character by character, something like:

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

int main(int argc, char **argv) {
    for (int i = 1; i < argc; i++) {
        for(int j = 0; argv[i][j] != '\0'; ++j) {
            if (!isalpha((unsigned char)argv[i][j])) {
                printf("NON-LETTER\n");
            }
        }
    }
    return 0;
}

  1. in particular, the char value casted to unsigned char casted to int, due to unfortunate reasons I detailed elsewhere.
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • you have a bad dereference in the expression `isalpha((unsigned char)argv[i][j])` – Ahmed Masud Jan 06 '20 at 02:11
  • 2
    @AhmedMasud: thank you, fixed. It was a remaining of a previous version where I straight used a pointer to iterate over the string, which I subsequently changed to indexing to ease it up for beginners. – Matteo Italia Jan 06 '20 at 02:13
  • 3
    You have a very kind way of commenting and answering, and I really appreciate that. Thank you. – Ahmed Masud Jan 06 '20 at 02:17
0

isalpha expects int, and your input argv[i] is char *. Depend on your code, you can judge letter or not according to ASCII.

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

int main(int argc, char **argv) {
  int i = 0;
  for (i = 1; i < argc; i++) {

    if (!(argv[i][0] >= 'a' && argv[i][0] <= 'z')) {
      printf("NON-LETTER\n");
    }
  }

  return 0;
}
douyu
  • 2,377
  • 2
  • 14
  • 27
0

The trouble is in this part of the code:

        if (!isalpha(argv[i])){
            printf("NON-LETTER\n");
        }

argv is a pointer to a pointer. (Think of it as an array of strings, and each string is an array of characters)

So, you need two loops, one that runs through the array of strings argv[k] and then another that looks at the kth string.

There is a hidden hint, only look at it if you have trouble:

Hint 1:

for (k = 1; k < argc; k++ ) { for ( j = 0; argv[k][j] != 0; j++ ) { if( !isalpha((unsigned char) argv[k][j]) { // do something here } } The (unsigned char) casting is necessary because of how argv[] (declared as a char) may be interpreted as a signed value, and when it gets recast to int (which will have a signed bit without the cast) will be misinterpreted by the checking function. it's explained further in the isalpha man page.

Community
  • 1
  • 1
Ahmed Masud
  • 21,655
  • 3
  • 33
  • 58