'Segmentation fault' as user doesn't has an input - c

I wanted to implement a program that changes the user his DNA-string to a RNA-string. But I have some problems with my code that I don't really understand. My code:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[])
{
int n = strlen(argv[1]);
if (argc != 2)
{
printf("Usage: ./rna ATGC\n");
return 1;
}
else if (argc == 2 && n >= 4)
{
for (int i = 0; i < n; i++)
{
if (argv[1][i] == 'A' || argv[1][i] == 'a')
{
printf("U");
}
else if (argv[1][i] == 'G' || argv[1][i] == 'g')
{
printf("C");
}
else if (argv[1][i] == 'C' || argv[1][i] == 'c')
{
printf("G");
}
else if (argv[1][i] == 'T' || argv[1][i] == 't')
{
printf("A");
}
}
return 0;
}
if (n <= 3)
{
printf("Invalid DNA\n");
}
}
If the user just runs the program I want to get an output like this:
$ ./rna
Usage: ./rna ATGC
But, I get this and can't really figure out what is wrong.
$ ./rna
Segmentation fault

Your checking the length (argc) of argv after accessing the element that does not exist. You cannot do strlen(argv[1]) before you're sure there is an argv[1]!

int n = strlen(argv[1]);
if there are no command-line arguments it invokes undefined behaviour.
change to:
size_t n = argc > 1 ? strlen(argv[1]) : 0;

Related

How to share the pass the value from child to parent in this inifinte unary operations

I am try to implement a program to do this type of calculation in which i have to use only some limited system calls
fork
exec* family
str* family
ato* family
printf, sprintf
round
The program name is double.c and the calculation looks like
./double square 3
output:36 as square(double(3))
I am using exit(result) to returning the result but as the range it is capable of is 0-255 but when the number exeeds from 255 it gives wrong result I have to impement this program just using these system api calls so i think pipe and munmap cannnot be used but how i can return bigger values than using just these functions
What i tried is
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <math.h>
#include <sys/wait.h>
#include <stdlib.h>
#define EPSILON 0.001
double simple_abs(double x)
{
return x > 0 ? x : -x;
}
double simple_sqrt(double x)
{
double previous = 0;
double guess = x;
while (simple_abs(guess - previous) > EPSILON)
{
previous = guess;
guess = previous - (previous * previous - x) / (2 * previous);
}
return guess;
}
int lop(int status) {
return (status >> 8) & 0xff;
}
int square(int n) {
printf("number = %d and square = %d\n", n , n*n);
return n * n;
}
int root(int n) {
return (int) simple_sqrt((double) n);
}
int doubleVal(int n) {
return n * 2;
}
int main(int argc, char *argv[]) {
int value = atoi(argv[argc - 1]);
int result = value;
if (argc > 2){
result = doubleVal(result);
for (int i = 1; i < argc - 1; i++) {
int pid = fork();
if (pid == 0) {
if (*argv[i] == 's' && *(argv[i]+1) == 'q' && *(argv[i]+2) == 'u' && *(argv[i]+3) == 'a' && *(argv[i]+4) == 'r' && *(argv[i]+5) == 'e' && *(argv[i]+6) == '\0'){
result = square(result);
} else if (argv[i][0] == 'r' && argv[i][1] == 'o' && argv[i][2] == 'o' && argv[i][3] == 't' && argv[i][4] == '\0') {
result = root(result);
} else if (argv[i][0] == 'd' && argv[i][1] == 'o' && argv[i][2] == 'u' && argv[i][3] == 'b' && argv[i][4] == 'l' && argv[i][5] == 'e' && argv[i][6] == '\0') {
result = doubleVal(result);
} else {
printf("Unknown operation: %s\n", argv[i]);
exit(1);
}
printf("Child result: %d\n", result);
//return result;
exit(result);
} else {
int status;
wait(&status);
//result = (status >> 8) & 0xff;
result = lop(status);#lop is working as WEXITSTATUS system api
}
}
}
else {
result = doubleVal(result);
}
printf("Result: %d\n", result);
return result;
}
Is there any way to do this to get correct result because when i try ./double square 8 it give wrong result as the result exceeds from 255 .

Function to allow for only alphabets, hyphens and apostrophes

As stated above, I would like to make a function that checks if all the characters in a string contains any prohibited input. The condition is that I only want to accept alphabets, hyphens and apostrophes. Below is my code which does not work the way I intended it to. If it is not an alphabet AND not an apostrophe or a hyphen, I want to change result to 0. However, when I enter a valid input like 'a-a; which is either an alphabet or hyphen, the if function still gets executed which prints "IT IS NOT ACCEPTED".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int validateInput(char word[]);
int main(void) {
char word[33] = "a-a";
printf("%d",validateInput(word));
}
int validateInput(char word[]) {
int result = 1;
int i;
int length = strlen(word);
for (i = 0; i <length; i++) {
if ((isalpha(word[i]) == 0) && ((word[i] != '-') || (word[i] != '\''))) {
printf("IT IS NOT ACCEPTED\n");
result = 0;
}
else {
printf("ACCEPTED\n");
}
}
return result;
}
There are multiple problems in your code:
you issue the diagnostic at each iteration instead of at the end of the loop
the test (word[i] != '-') || (word[i] != '\'') is always true.
isalpha() should not be passed a char value that could be negative. You should cast the argument as (unsigned char) to avoid potential undefined behavior.
Here is a modified version:
#include <ctype.h>
int validateInput(const char *word) {
int result = 1;
for (size_t i = 0; word[i] != '\0'; i++) {
if (!isalpha((unsigned char)word[i]) && word[i] != '-' && word[i] != '\'') {
result = 0;
break;
}
}
if (result) {
printf("ACCEPTED\n");
} else {
printf("IT IS NOT ACCEPTED\n");
}
return result;
}
Note however that the above function will accept an empty string, which might not be the intended behavior.
Here is a simpler version using sscanf() that works for ASCII:
#include <stdio.h>
int validateInput(const char *word) {
int pos = 0;
sscanf(word, "%*[-a-zA-Z']%n", &pos);
if (pos > 0 && word[pos] == '\0') {
printf("ACCEPTED\n");
return 1;
} else {
printf("IT IS NOT ACCEPTED\n");
return 0;
}
}
And this is a more verbose version using strspn() that works for all encodings:
#include <string.h>
int validateInput(const char *word) {
size_t len = strspn(word, "'-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
if (len > 0 && word[len] == '\0') {
printf("ACCEPTED\n");
return 1;
} else {
printf("IT IS NOT ACCEPTED\n");
return 0;
}
}
Try:
if( !( (isalpha((unsigned char)word[i])) || (word[i] == '-') || (word[i] == '\'')) )

Malfunction, unkown reason

I have to examine passwords. The password is strong, when it contains uppercases, lowercases, digits and at least 8 characters. I wrote this C program, but it always displays "weak password". I don't know the reason.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 50
int strenght(char word[],int length)
{
int sup = 0;
int low = 0;
int dig = 0;
for(int i = 0; i < length; i++)
{
if(isupper(word[i]) == 1)
sup++;
else if(islower(word[i]) == 1)
low++;
else if(isdigit(word[i]) == 1)
dig++;
}
if(sup > 0 && low > 0 && dig > 0 && length >= 8)
return 1;
else
return 0;
}
int main()
{
printf("Type the password until '*'\n");
char word[N];
while(1)
{
printf("Password: ");
fgets(word, N, stdin);
int length = strlen(word) - 1;
if(word[0] == '*')
break;
else
{
if(strenght(word, length) == 1)
printf("Strong password\n");
if(strenght(word, length) == 0)
printf("Weak password\n");
}
}
return 0;
}
The problem is that you are comparing the results of the isupper, islower and isdigit calls to 1. Don't do this! Each of these functions will return zero if the condition is not satisfied and any non-zero value if it is satisfied. (see cppreference).
So, in place of:
if(isupper(word[i]) == 1)
sup++;
just do this:
if(isupper(word[i]))
sup++;
or, if you want to keep the explicit nature of the comparison, use:
if(isupper(word[i]) != 0)
sup++;
(And similarly for the other tests.)

C program error:checking if password is valid

I'm trying to create a c program that checks if the password contains at least :
-1 special character
-1 lowercase letter
-1 uppercase letter
-1 digit
when i test it, it doesn't work for some reason i've been trying to figure out my error but i didn't know what was wrong
this is my attemp :
//check password =at least one upper /at least 1 lower/ at least 1 char;
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
void main() {
char pass[20]; //password
int a = 0; //size of the password
int foundChar = 0;
int foundUpper = 0;
int foundLower = 0;
int foundDigit = 0;
int i = 0;
do {
printf("enter your password : ");
scanf("%s", pass);
a = strlen(pass);
if (a = 8) {
if (isdigit(pass[i]) && foundDigit == 0) {
foundDigit = 1;
i++;
} else if (isupper(pass[i]) && foundUpper == 0) {
foundUpper = 1;
i++;
} else if (islower(pass[i]) && foundLower == 0) {
foundLower = 1;
i++;
} else if (foundChar == 0) {
foundChar = 1;
i++;
}
}
}
while ((a < 8) || (foundChar == 0) || (foundDigit == 0) || (foundUpper == 0) || (foundUpper = 0));
}
You are not looping through the password.
After your if (a >= 8) statement, there is no code to loop around and examine the remaining characters in the string.

How to create a process for each vowel?

I am new at Processes. I read a lot but I didn't really understand how it works. I try to make a process for each vowel in a char string. I have to delete all vowels from that string. I know that I have to use fork, but I don't know how. I tried to write the code, but what I receive was Core Dumped.
#include <unistd.h>
#include <stdio.h>
#include <string.h>
char sir[100];
int vocal(char x)
{
if(x=='a' || x=='e' || x=='i' || x=='o' || x=='u' || x=='A'||
x=='E' || x=='I' || x=='O' || x=='U')
return 1;
return 0;
}
int main(){
printf("Read the text: \n");
read(1,sir,100); // file descriptor is 1;
pid_t a_Process;
for(int i=0;i<strlen(sir);i++)
{
if(vocal(sir[i])==1)
{
a_Process=fork();
for(int j=i;j<strlen(sir)-1;i++)
sir[j]=sir[j+1];
}
}
printf("%s",sir);
return 0;
}
I didn't understand how the child process and everything goes. Thank you very much!
Try this code:
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char sir[100];
int vocal(char x)
{
if (x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u' ||
x == 'A' || x == 'E' || x == 'I' || x == 'O' || x == 'U')
return 1;
return 0;
}
int main()
{
int i, j, pid_status;
printf("Read the text: \n");
// read(1,sir,100); // file descriptor is 1;
fgets(sir, 100, stdin);
pid_t a_Process;
for (i = 0; i < strlen(sir); i++)
{
if (vocal(sir[i]) == 1)
{
printf("detected a vowel\n");
a_Process = fork();
if (a_Process == -1)
{
fprintf(stderr, "Can't fork a process.\n");
return 1;
}
if (a_Process)
{
printf("Starting a new child .... \n");
for (j = i; j < strlen(sir) - 1; j++)
sir[j] = sir[j + 1];
}
// The following statement is needed such that
// child process starts one after the other.
if (waitpid(a_Process, &pid_status, 0) == -1)
{
printf("Error waiting for child process.\n");
}
}
}
printf("%s", sir);
return 0;
}

Resources