This is a program that takes the arguments passed by the user, checks if it's a letter, and concatenates them in an array:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char **argv)
{
char frase[80] = "";
for(int i = 1; i < argc; i++) {
printf("%s", argv[i]);
if(isalpha(argv[i]))
strcat(frase, argv[i]);
}
printf("%s\n", frase);
}
I have used gdb (also with the core option) and there are no errors, yet I get Segmentation Fault (core dumped). The code works if I remove if(isalpha(argv[i])). Any help would be appreciated, thank you.
The argument to isalpha is one character, not a pointer to a string of characters. Passing it a pointer might cause it to reference undefined memory by indexing out of the table of characters it uses.
Related
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[])
{
int i=0;
int x=0;
int n=0;
argv[i]=GetString()
printf("%c", toupper(argv[i][0]));
for (x=0, n=strlen(argv[i]); x<n; x++)
{
printf("%c", toupper(argv[i+1][0]));
}
printf("\n");
}
The code compiles but does not print the initials of a name entered by the user. For instance, John Smith: JS. I receive a segmentation fault instead.
This program is initials.c for CS50.
Although you didn't show the definition of GetString(), I'm pretty sure you're not calling it correctly, because there's no semicolon after it and you almost certainly do not want to overwrite argv[0]. Compiling with debugging symbols (-g in GCC) and running in a debugger will tell you which line of code crashed the program.
Edit: My guess is that you're crashing when you try to dereference argv[i+1], which is argv[1], a NULL pointer. But running in a debugger could confirm or disconfirm this. You seem to be mixing up the syntax to loop through an argument list with the syntax to read a line from standard input.
It is unorthodox to use argv[0] to hold a pointer to the return value from CS50's GetString() function, though not actually illegal.
You have a syntax error; you've omitted a semicolon after GetString().
With that fixed, your crash-causing problem is in the indexing in the loop; you are indexing argv[i+1][0], but argv[1] is a null pointer unless you provided command line arguments and accessing the null pointer is often a crash (so we can tell you didn't provide any command line arguments).
You can demonstrate with:
$ ./initial xyz <<< "john smith"
JXXXXXXXXXX
$
It didn't crash, and it did repeatedly copy the first letter of the argument converted to upper case (because you keep accessing argv[i+1][0]).
The fixes are correspondingly simple:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
int x = 0;
int n = 0;
string str = GetString();
printf("%c", toupper(str[0]));
for (x = 0, n = strlen(str); x < n; x++)
{
printf("%c", toupper(str[x]));
}
printf("\n");
free(str);
return 0;
}
Example run
$ ./initials <<< "john smith"
JJOHN SMITH
$
This isn't the required output, but it does show the program working safely and gives you a decent basis from which to work to get the correct answer.
So I am new to the C language, I am attempting to write a program that outputs text in either upper or lower case, by inputting either -u or -l. The program compiles, however when I run it, it gives me a segmentation fault. Why?
#include <stdio.h>
#include <string.h>
int main(int argc, char*argv[]){
int i;
int j;
int k;
if(strcmp(argv[1],"-u")){
for(i=0;i<argc;i++){
printf("%s ",toupper(argv[i]));
}
}
else if(strcmp(argv[1],"-l")){
for(j=0;j<argc;j++){
printf("%s ",tolower(argv[j]));
}
}
else{
for(k=0;k<argc;k++){
printf("%s ",argv[k]);
}
}
}
toupper & tolower take an int representing a character and returning an int representing that character as upper or lower case (respectively).
You're doing 2 things wrong with that:
You're passing in the address of a char array (not a single character)
You're using the returned value (int) as if it was a char array (passing it as an input to printf with "%s")
So you're getting some garbage out of the function, and then sending printf into unmapped memory address -> that's your seg-fault.
To make life easy, also consider using the getopt command.
Here you will find an example: http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html#Example-of-Getopt
when i try to execute this code i "segmentation fault"appears on the screen. Can someone please tell me what the error is? thanks in advance
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char * argv[]){
int fd , i;
int count= atoi(argv[2]);
char name[50];
char nname[50];
strcpy(nname, "./lfille");
strcpy(name, argv[1]);
struct stat statbuf;
/* if((fd=open(argv[1], O_RDWR)==-1)){
fprintf(stderr, "Datei existiert nicht\n");
}else*/ if((lstat(argv[1], &statbuf)==-1)){
fprintf(stderr, "Error bei lstat\n");
}else if(!(S_ISREG(statbuf.st_mode))){
printf("%s ist nicht REG\n ", argv[1]);
exit(1);
}else{
for(i=0; i<count; i++){
printf("%s", nname);
symlink(name, nname);
sprintf(name,"%s", nname);
sprintf(nname, "./lfille%d", i);
}
}
return 0;
}
I compiled the source code with gnu gcc 4.8.2.
The program worked fine for me. I think you are only passing one argument to the program instead of two. This is why. I suggest what Weather Vane said in his answer.
The parameter *argv[] is an array of string pointers, with argc informing the length of this array.
The first element argv[0] points to a string holding the program name. If there were any runtime arguments supplied when the program is run, a string pointer is supplied for each one, with the appropriate value in argc to tell you how many elements of the string pointer array have been supplied. If there were no program arguments supplied, *argv[] array will have a length of 1.
If you try to access the arguments that should have been given, you will be indexing beyond the length of the array *argv[] which leads to undefined behaviour. You will be dereferencing a pointer which has an essentially random value. This might be benign, or it might lead to the segmentation fault due to trying to access memory you are not allowed.
I suggest any program which takes (say 2) user arguments at run time have checking code similar to this:
if (argc < 3) {
printf ("Syntax should be: %s filename links\n", argv[0]);
exit (1);
}
Currently I have a code that passes arguments to main and I use the strstr tool to see if the arguments or strings passed to it are subsets of each other. If they are not, I get the message (null). However, when I try to take advantage of this with an if statement it doesn't seem to activate?
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
for(i=1; i<argc; i++)
{
printf("%s\n", argv[i]);
}
printf("\n");
char *chant;
chant = strstr(argv[1], argv[2]);
printf("The subtring is: %s\n", chant);
if(chant==NULL)
{
printf("good bye");
}
return 0;
}
So if I enter something like hello helloow, it will say "The substring is: (null)" and from there I want my if statement to activate and print "good bye". Isn't chant NULL when strstr can't find a substring? I know there is something wrong with my if statement syntax, but not sure >....
I have tried this as well:
if(*chant!=NULL)
but it gives me this comparison error about pointer and integer.
EDIT:
I don't know WHY, but it seems that if I use GCC instead of CC to comnpile then it will work.. This is very odd..
printf() expects a valid (non-NULL) char* matching the %s. Passing a (char*)NULL is technically undefined behaviour. glibc printf(), for probably bad reasons, decides that "undefined behaviour" to them means printing "(null)".
But the C-compiler sees you dereference a pointer, and then afterwards check whether it was NULL. The compiler is free to conclude that, since you've already dereferenced that pointer, and the world hasn't ended, that pointer wasn't NULL, so it removes the if(!chant){//can't happen}. Welcome to C.
To get defined behaviour, you could go with code like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 3)
exit(EXIT_FAILURE); //to avoid passing a NULL-ptr to printf()/strstr()
int i;
for(i=1; i<argc; i++)
{
printf("%s\n", argv[i]);
}
printf("\n");
char *chant;
chant = strstr(argv[1], argv[2]);
printf("The subtring is: %s\n", chant?chant:"(null)");
//prints "(null)" when substring not found, substring otherwise
if(chant==NULL)
{
printf("good bye");
}
return 0;
}
I'm having a problem with the program below. I'm trying to scan through a string command entered by the user for certain words. My major issue right now is that when I run the following I get a warning saying that "passing arg 2 of `strcat' makes pointer from integer without a cast". My intent is to loop through the first three characters of the string "s", concatenate them onto a string "firstthree", and later check the value of the string "firstthree". Any help is appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <readline/readline.h>
#include <readline/history.h>
/* Simple example of using gnu readline to get lines of input from a user.
Needs to be linked with -lreadline -lcurses
add_history tells the readline library to add the line to it's
internal histiry, so that using up-arrow (or ^p) will allows the user
to see/edit previous lines.
*/
int main(int argc, char **argv) {
char *s;
while (s=readline("Enter Name: ")) {
add_history(s); /* adds the line to the readline history buffer */
printf("Hello %s\n",s);/*output message to the user*/
char *firstthree;
int i;
for(i = 0; i < 3; i++){
strcat(firstthree, s[i]);
printf("Hello %s\n",firstthree);//checking to see the character added to the end of the string
}
printf("Hey %s\n",firstthree);/*prints out the first three characters*/
free(s); /* clean up! */
free(firstthree);
}
return(0);
}
Your program has a lot of problems; you never initialize firstthree, for example.
The reason you're getting the specific error you're seeing is because of this call:
strcat(firstthree, s[i]);
s is a char *, so s[i] is a char, but strcat expects both parameters to be pointers to null-terminated strings. What it seems you want is something like:
char firstthree[4] = { 0 };
for (int i = 0; i < 3; i++)
{
firstthree[i] = s[i];
printf("Hello %s\n", firstthree);
}
You can't use strcat() to do this; it requires two char* s as arguments, not a char* and a char. You could use strncat() if it is available on your platform.