简体   繁体   中英

C - Segmentation fault (core dumped) error when running my program

In order to practice in c, in my caesar.c program I'm using my encrypt_text method in order to encrypt a given text (for which user is prompted). I'm using the Caesar cipher function and as a key, I'm using the argv[1] element (casted in int).

In the first if statement I check that, running the program, the user types only one element (after the program name), that the element is not a zero and that is composed by only digits (trough the helper method checkString ). If the conditions are respected, the user is prompted for the text to encrypt. Otherwise the user is asked to run the program again with the message: Usage:./caesar Key .

So, everything seems to work correctly but, when I run the program typing only the name of the program (so, basically, filling argv[] array with only one element), I encounter a segmentation fault (core dumped) error.

So, if I run the program with the command ./caesar 3 everything works correctly but if I run the program with the command ./caesar (without a number after it), then the segmentation fault error happens.

Basically, also in this last case, I need the same Usage:./caesar Key message to be returned.

I read a lot about this kind of problem that is related to trying to access memory that is not allowed but, at the moment, I did not find the reason why is happening in my specific program.

Some suggestion?

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

void encrypt_text (string text, const int tlen, int shift, char* cipher);//encrypt method
int checkString(string strToCheck);

int main(int argc, string argv[])
{
    int key = atoi(argv[1]);//cast argv[1] to an integer

    if ((argc == 2) && (key != 0) && checkString(argv[1]) == 1)
    {

        //include cypher method
        string text = get_string("Text to cypher: ");
        int tlen = strlen(text);
        char cipher[tlen +1]; cipher[tlen] ='\0';
        int shift = key; // key

        //printf ("Text :\t\t%s\n", text);
        encrypt_text (text, tlen, shift, cipher);
        printf ("ciphertext:%s\n", cipher);
        text[0] = '\0';
        return 0;

    } else {
        printf("Usage: ./caesar Key \n");
         return 1;
    }
}


//encrypting method
void encrypt_text (string text, const int tlen, int shift, char* cipher) {
    char lower[] = "abcdefghijklmnopqrstuvwxyz";
    char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    shift %= 26; // more than 26 make cycle[s]
    for (int ti=0; ti < tlen; ++ti) {
        if (islower (text[ti]))
            cipher[ti] = lower[(text[ti] - 'a' + shift) % 26];
        else if (isupper (text[ti]))
            cipher[ti] = upper[(text[ti] - 'A' + shift) % 26];
        else
            cipher[ti] = text[ti];
    }
}


//helper method for checking only digits strings
int checkString(string strToCheck) {

      for (int i = 0, n = strlen(strToCheck); i < n; i++) {
          int test = isdigit(strToCheck[i]);

          if (test == 0) {
              return 0;//found a non digit
              break;
          }
      }
return 1;//string has only digit
}

When your program is executed with no arguments, argv[1] won't have any information about the arguments. NULL is put there in some environments.

Therefore, you mustn't execute atoi(argv[1]) in this case.

Check should be added to the statement

int key = atoi(argv[1]);

like

int key = 0;
if (argv >= 2) {
    key = atoi(argv[1]);
}

or (if using ternary operator is allowed):

int key = argv >= 2 ? atoi(argv[1]) : 0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM