I am having the following issue: Segmentation fault (core dumped).
I looked around at the other questions on StackOverflow and didn't see the correct answer to my question. Here is my code :
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("missing command-line argument\n");
return 1;
}
for (int i = 0; i < argc; i++)
{
printf("Made it inside");
if (isdigit(argv[i]) == 0)
{
return 1;
}
}
string plain_text = get_string("plaintext: ");
int key = atoi(argv[1]); //function to convert a string to int.
for (int i = 0, n = strlen(plain_text); i < n; i++)
{
int c = (int) plain_text[i];
c += key;
printf("%c", c);
}
printf("\n");
return 0;
}
The error is coming from "if (isdigit(argv[i]) == 0)".
EDIT:
Here is the solution, thanks all!
for (int i = 0; i < strlen(argv[1]); i++)
{
if (isdigit(argv[1][i]) == 0)
{
return 1;
}
}
You are passing a string which is actually a char * to isdigit. You need to pass the first character of the string instead
isdigit(*argv[i][0])
isdigit expects an int, you're giving it a string (actually a null terminated group of chars)
http://pubs.opengroup.org/onlinepubs/009696699/functions/isdigit.html
While the behavior is listed as "undefined" in this case, I'm not actually sure why you would get a segfault from it.
Related
i'm new to CS and have been tackling cs50. its been a great experience so far as I was a math major and most of the concepts and assignments have been clicking really well.
i know part of the learning process is to solve your bugs yourself, but after a few hours staring at the one line that i narrowed down is causing the segmentation fault, I'm getting pretty frustrated.
I've attached my code below. i spent an hour watching a tutorial on pointers but still can't narrow down why I can pass in argv[1] to my function validateKey() but can't access the memory when i try to use it.
I saw experienced programmers stating that its crucial to be able to identify where exactly the segmentation fault is arising, so after debugging I noticed anytime in the program I try to access argv[1] (whether in main or local), that memory access is restricted
greatly appreciate your time and support!
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
int findIndex(char keyVal);
void cipherText(string s, string key);
bool validateKey(string s);
string alphabet = "abcdefghijklmnopqrstuvwxyz";
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage ./substitution key\n");
return (1);
}
int length = strlen(argv[1]);
if (length != 26)
{
printf("Key must contain 26 characters\n");
return (1);
}
else
{
if (validateKey(argv[1])) //allows to pass argv[1]
{
string userText = get_string("plaintext: ");
cipherText(userText, argv[1]); //allows to pass
printf("\n");
return (0);
}
else
{
printf("Usage ./substitution key\n");
return (1);
}
}
}
bool validateKey(string s)
{
int n = strlen(s);
int hash[n][1];
for (int i = 0; i < n; i++)
{
int b;
if (isdigit(s[i]))
{
return false;
}
b = s[i];
if (hash[b][0] == 1)
{
return false;
}
else hash[b][0] = 1;
}
return true;
}
int findIndex(char keyVal)
{
for (int i = 0; i < 26; i++)
{
if (alphabet[i] == tolower(keyVal) || alphabet[i] == toupper(keyVal))
{
return i;
break;
}
}
return -1;
}
void cipherText(string s, string key)
{
printf("ciphertext: ");
for (int i = 0, n = strlen(s); i < n; i++)
{
if (!(isalnum(s[i])) || isdigit(s[i]))
{
printf("%c", s[i]);
continue;
}
int index = findIndex(s[i]);
if (index < 0) break;
if (isupper(s[i]))
{
printf("%c", toupper(key[index])); //SEGMENTATIONF
continue;
}
else if (islower(s[i]))
{
printf("%c", tolower(key[index]));
}
else printf("%c", s[i]);
}
}
I was doing the cs50 pset 2 - substitution, where we have to encrypt the plaintext using the key given by the user in the command line, but the following code isn't prompting for an input. What am I doing wrong? Any help would be greatly appreciated!
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int check(int c, string key);
int main(int argc, string argv[])
{
int checkR = check(argc, argv[1]);
if(checkR == 1)
{
return 1;
}
else
{
string key = argv[1];
string ptext = get_string("plaintext: ");
int len = strlen(ptext);
char ctext[len];
for (int i = 0; i < len; i++)
{
if(isupper(ptext[i]))
ctext[i] = toupper(key[(int)ptext[i] - 65]);
else if(islower(ptext[i]))
ctext[i] = tolower(key[(int)ptext[i] - 97]);
else
ctext[i] = ptext[i];
}
printf("ciphertext: %s\n", ctext);
return 0;
}
}
int check(int c, string key)
{
int keyL = strlen(key);
if(c != 2)
return 1;
else if(keyL != 26)
return 1;
for(int i = 0; i < keyL - 1; i++)
{
for(int j = i; j < keyL; j++)
{
if(key[i] == key[j])
return 1;
}
}
return 0;
}
Answer for the question
In the check function, you initialized the inner loop as int j = i.
Therefore, in the first iteration, key[i] == key[j] will be always true.
Then, 1 is returned from check and it prevents main function from printing the prompt.
The initialization should be int j = i + 1.
Other mistakes
Firstly, it is bad to do int keyL = strlen(key); before checking c because key (argv[1]) may be NULL when c (argc) is less than 2.
Secondly, printf("ciphertext: %s\n", ctext); in this code will invoke undefined behavior because what is stored in ctext is not NUL-terminated.
char ctext[len]; should be char ctext[len+1]; and ctext[len]='\0'; should be added before printf("ciphertext: %s\n", ctext);.
I am trying to access each character in a string and add 1 to it before printing out the text. Eg. my code will prompt the user for a text ie. hello and it should print that text plus 1 character(i.e. output "ifmmp" when the input is "hello"). From my code below, instead of a for loop, I am trying to use a while loop to do this however I am running into some issues and it doesn't seem to print the response. Any help greatly appreciated.
// Libraries
#include <cs50.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
// If
if (argc == 2 && (atoi(argv[1]) > 0))
for(int i = 0, len = strlen(argv[1]); i < len; i++)
{
char n = argv[1][i];
int digit = isdigit(n);
if (!digit)
{
printf("Usage: ./caesar key\n");
return 1;
}
else
{
string plain = get_string("plaintext: ");
int k = 0;
int len_plain = strlen(plain);
while (len_plain > k)
k++;
char cipher = plain[k];
{
printf("%c\n", cipher);
}
}
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
Your question seems to be:
am trying to access each character in a string and add 1 to it before printing out the text
That can be done in many different ways - here is one example:
#include <stdio.h>
int main(void) {
char str[10] = "hello";
int i = 0;
while(str[i])
{
++str[i]; // Add 1
++i;
}
printf("%s\n", str);
return 0;
}
Output:
ifmmp
#include <stdio.h>
#include <string.h>
int convert(char *str)
{
int i, number = 0;
for (i = 0; str[i] != '\0'; ++i) {
number = number * 10 + str[i] - '0';
}
return number;
}
int main(int argc, char *argv[])
{
int j;
int c = convert(argv[2]);
if (argc == 3) {
for (j = 0; j < c; j++) {
printf("Hello, %s!\n", argv[1]);
}
} else if (argc < 3) {
printf("Not Enough Arguments\n");
} else if (argc > 3) {
printf("Too Many Arguments\n");
}
return 0;
}
getting segmentation fault when giving less then 3 arguments.
on giving less than 3 arguments it should print "not enough arguments" but it gives error segmentation fault.
input:./a raju
expected output: not enough arguments
int c = convert(argv[2]);
When argc is 2, argv[2] will be NULL. What do you expect this line of code will do, as it's executed first thing when the program runs?
Refactoring so that the conditionals below it form a guard against that condition, here's something closer to what you probably intended:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int convert(char *str)
{
int i, number = 0;
for (i = 0; str[i] != '\0'; ++i) {
number = number * 10 + str[i] - '0';
}
return number;
}
int main(int argc, char *argv[])
{
if (argc != 3) {
printf( argc < 3 ? "Not Enough Arguments\n"
/*argc > 3*/ : "Too Many Arguments\n" );
exit(EXIT_FAILURE);
}
int c = convert(argv[2]);
for (int j = 0; j < c; j++) {
printf("Hello, %s!\n", argv[1]);
}
return 0;
}
P.S. As argv[0] is typically the program name rather than an argument, argv[1] and argv[2] will be your arguments, argv[3] will be NULL and if you count them you'll count two arguments, not three; expect argc == 4 when three arguments are given.
You may be interested in getopt.h library. It handles all the standard features of command line arguments.
I'm looking to replace words from a file where words.txt contains "banana test apple" would output -> "banana Replaced! apple" The words it would be looking to replace would come as an argument to stdin ("test" in this case)
Not sure where my code is going wrong, and I'm also wondering if there's a better way to do it than get getchar() function, as I find it confusing to work with, and annoying as you cannot backup characters.
Any suggestions? Thanks
$ ./a.exe test < words.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
int c = getchar();
int counter = 0;
int i,index;
for (i = 1; i < argc; i++){
for (index = 0; index < strlen(argv[i]); index++){
while (c == argv[i][index]){
counter++;
c = getchar();
index++;
if (counter == strlen(argv[i])){
printf("Replaced!");
}
}
printf("%c ",c);
c = getchar();
counter = 0;
}
}
return (0);
}
I would do it as follows :
read all the file into a buffer using fgets
looking for the key work (test) using strstr
replace it with your new string using strncpy
write to file (or output to stdout) whatever you want to do
You could use scanf to read in a word at a time:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char wordbuffer[100];
while (scanf("%99s", wordbuffer) == 1)
{
int replace = 0;
for (int i = 1; i < argc && !replace; i++)
if (strcmp(wordbuffer, argv[i]) == 0)
replace = 1;
if (replace)
printf("Replaced! ");
else
printf("%s ", wordbuffer);
}
}
If you are using a modern system that compliant with the latest POSIX specification, you can take advantage of the m assignment-allocation character, and have the appropriate amount of space allocated for you, so that you don't have to use some arbitrary maximum number of characters.
int main(int argc, char *argv[])
{
char *wordbuffer;
while (scanf("%ms", &wordbuffer) == 1)
{
int replace = 0;
for (int i = 1; i < argc && !replace; i++)
if (strcmp(wordbuffer, argv[i]) == 0)
replace = 1;
if (replace)
printf("Replaced! ");
else
printf("%s ", wordbuffer);
free(wordbuffer);
}
}