why does c allow initialization of string without declaration? - c

When the arguments of dyn_mat are constants, the code runs through without any error and s1 and s2 do store the input values.
#include<stdio.h>
int main(int argc, char const *argv[])
{
char *s1, *s2;
int n1=7, n2=8;
printf("Enter, %d \n", n1);
scanf("%s", s1);
scanf("%s", s2);
int dyn_mat[155][347];
return 0;
}
but with arguments as variables, say n1 and n2, scanf reading s1 gives segmentation fault.

The code simply has undefined behaviour, since s1 and s2 are not valid pointers. scanf expects a pointer to an array of chars that's large enough to hold the read data, and you are not providing such pointers.
The usual way would be something like this:
char s1[1000];
char s2[1000];
scanf("%s", s1);
scanf("%s", s2);
(Though you should use a safer version that specifies the available buffer size rather than hoping for the input to be sufficiently short; for example, scanf("%999s", s1);.)

why does c allow initialization of string without declaration?
There is no data type string in C.
In C one possible way to store a string of characters is using an array of characters, with the last element of this array carring a 0 to indicate the end of this string.
You program does not declare any array, but just pointers to characters, which have no memory assigned to which you copy data using scanf().
Your just lucky the program does not crash with the first call to scanf().

Related

How to return a string to main function?

I am trying to write code to implement strchr function in c. But, I'm not able to return the string.
I have seen discussions on how to return string but I'm not getting desired output
const char* stchr(const char *,char);
int main()
{
char *string[50],*p;
char ch;
printf("Enter a sentence\n");
gets(string);
printf("Enter the character from which sentence should be printed\n");
scanf("%c",&ch);
p=stchr(string,ch);
printf("\nThe sentence from %c is %s",ch,p);
}
const char* stchr(const char *string,char ch)
{
int i=0,count=0;
while(string[i]!='\0'&&count==0)
{
if(string[i++]==ch)
count++;
}
if(count!=0)
{
char *temp[50];
int size=(strlen(string)-i+1);
strncpy(temp,string+i-1,size);
temp[strlen(temp)+1]='\0';
printf("%s",temp);
return (char*)temp;
}
else
return 0;
}
I should get the output similar to strchr function but output is as follows
Enter a sentence
i love cooking
Enter the character from which sentence should be printed
l
The sentence from l is (null)
There are basically only two real errors in your code, plus one line that, IMHO, should certainly be changed. Here are the errors, with the solutions:
(1) As noted in the comments, the line:
char *string[50],*p;
is declaring string as an array of 50 character pointers, whereas you just want an array of 50 characters. Use this, instead:
char string[50], *p;
(2) There are two problems with the line:
char *temp[50];
First, as noted in (1), your are declaring an array of character pointers, not an array of characters. Second, as this is a locally-defined ('automatic') variable, it will be deleted when the function exits, so your p variable in main will point to some memory that has been deleted. To fix this, you can declare the (local) variable as static, which means it will remain fixed in memory (but see the added footnote on the use of static variables):
static char temp[50];
Lastly, again as mentioned in the comments, you should not be using the gets function, as this is now obsolete (although some compilers still support it). Instead, you should use the fgets function, and use stdin as the 'source file':
fgets(string, 49, stdin);/// gets() has been removed! Here, 2nd argument is max length.
Another minor issue is your use of the strlen and strncpy functions. The former actually returns a value of type size_t (always an unsigned integral type) not int (always signed); the latter uses such a size_t type as its final argument. So, you should have this line, instead of what you currently have:
size_t size = (strlen(string) - i + 1);
Feel free to ask for further clarification and/or explanation.
EDIT: Potential Problem when using the static Solution
As noted in the comments by Basya, the use of static data can cause issues that can be hard to track down when developing programs that have multiple threads: if two different threads try to access the data at the same time, you will get (at best) a "data race" and, more likely, difficult-to-trace unexpected behaviour. A better way, in such circumstances, is to dynamically allocate memory for the variable from the "heap," using the standard malloc function (defined in <stdlib.h> - be sure to #include this header):
char* temp = malloc(50);
If you use this approach, be sure to release the memory when you're done with it, using the free() function. In your example, this would be at the end of main:
free(p);

why printf is not showing string on removing & and not showing address in C?

#include<stdio.h>
void main(){
char *r;
printf("Enter the string : ");
scanf("%s",&r);
printf("\nThe string is : %s",&r);
}
i am using DEV C++ (tdm-gcc 4.9.2 64-bit release)
in printf statment & removal will lead to printing of string but it is showing no output which confuses me alot
and i read that we can also use scan without & in case of string but it also not working in C
There is a big difference between char buf[64] and char *buf.
I suggest you to know the difference by printing sizeof those two declarations.
EX:
char *r;
char buf[64];
printf(" Size of array :%d pointer :%d\n", sizeof(buf), sizeof(r));
char *r; is pure declaration of a pointer which hold address of a char type variable.
char *r is char pointer, and right now it is pointing to junk value.
char buf[64], is char buffer of 64 bytes and buf is pointing to the first character.
char *r is pointing unknown/junk value. Before using this kind of approach, you should allocate memory.
char *r = (char *) malloc(32);
or
char buf[64];
char *r;
r = buf;
---> Now 'r' is pointing to buf, which already has memory allocated.
Now, you can understand the difference.
The %s format specifier to scanf expect a pointer to the first element of an array of char. In other words, a char *. You are instead passing a char **. Using the wrong format specifier invokes undefined behavior.
Define r as an array:
char r[100];
Then you can pass r to scanf, which decays into a pointer to the first element:
scanf("%99s", r);
Note also that we specify a maximum length here so that there is no risk of writing past the end of the array if too many characters are entered.
Similarly with printf, you need to call it as follows:
printf("\nThe string is : %s",r);

Char arrays and scanf function in C

I expected to get errors in following code, but I did not. I did not use & sign. Also I am editing array of chars.
#include <stdio.h>
int main()
{
char name[10] ="yasser";
printf("%s\n",name);
// there is no error ,
// trying to edit array of chars,
// also did not use & sign.
scanf("%s",name);
// did not use strcpy function also.
printf("%s\n",name);
return 0;
}
I expected to get errors in following code, but I did not.I did not use & sign.
scanf("%s",name);
That's totally ok as name is already the address of the character array.
It sounds like you have several questions:
calling scanf("%s", name) should have given an error, since %s expects a pointer and name is an array? But as others have explained, when you use an array in an expression like this, what you always get (automatically) is a pointer to the array's first element, just as if you had written scanf("%s", &name[0]).
Having scanf write into name should have given an error, since name was initialized with a string constant? Well, that's how it was initialized, but name really is an array, so you're free to write to it (as long as you don't write more than 10 characters into it, of course). See more on this below.
Characters got copied around, even though you didn't call strcpy? No real surprise, there. Again, scanf just wrote into your array.
Let's take a slightly closer look at what you did write, and what you didn't write.
When you declare and initialize an array of char, it's completely different than when you declare and initialize a pointer to char. When you wrote
char name[10] = "yasser";
what the compiler did for you was sort of as if you had written
char name[10];
strcpy(name, "yasser");
That is, the compiler arranges to initialize the contents of the array with the characters from the string constant, but what you get is an ordinary, writable array (not an unwritable, constant string constant).
If, on the other hand, you had written
char *namep = "yasser";
scanf("%s", namep);
you would have gotten the problems you expected. In this case, namep is a pointer, not an array. It's initialized to point to the string constant "yasser", which is not writable. When scanf tried to write to this memory, you probably would have gotten an error.
When you pass arrays to functions in C, they decay to pointers to the first item.
Therefore for:
char name[] ="yasser";
scanf("%s", name) is the same as scanf("%s", &name[0]) and either of those invocations should send shivers down your spine, because unless you control what's on your stdin (which you usually don't), you're reading a potentially very long string into a limited buffer, which is a segmentation fault waiting to happen (or worse, undefined behavior).
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
char *myName = (char *) calloc(10, sizeof(char));
*(myName)='K'; *(myName+1)='h'; *(myName+2)='a'; *(myName+3)='l'; *(myName+4)='i'; *(myName+5)='d';
printf("%s\n",myName);
scanf("%s",myName);
printf("%s\n",myName);
return (EXIT_SUCCESS);
}
#include <stdio.h>
#include <string.h>
int main()//fonction principale
{
char name[10] ="yasser";
int longeur=0;
printf("%s\n",name);
scanf("%s",name);
longeur = strlen(name);
for (int i=0;i<longeur;i++) {
printf("%c",*(name+i));
}
return 0;}

C strcat() gives wrong appended string

I am appending a string using single character, but I am not able to get it right. I am not sure where I am making mistake. Thank you for your help in advance. The original application of the method is in getting dynamic input from user.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){
int j;
char ipch=' ';
char intext[30]="What is the problem";
char ipstr[30]="";
printf("Input char: ");
j=0;
while(ipch!='\0'){
//ipch = getchar();
ipch = intext[j];
printf("%c", ipch);
strcat(ipstr,&ipch);
j++;
}
puts("\n");
puts(ipstr);
return;
}
Following is the output I am getting.
$ ./a.out
Input char: What is the problem
What is h e
p
oblem
change
strcat(ipstr,&ipch);
to
strncat(ipstr, &ipch, 1);
this will force appending only one byte from ipch. strcat() will continue appending some bytes, since there's no null termination character after the char you are appending. as others said, strcat might find somewhere in memory \0 and then terminate, but if not, it can result in segfault.
from manpage:
char *strncat(char *dest, const char *src, size_t n);
The strncat() function is similar to strcat(), except that
it will use at most n characters from src; and
src does not need to be null-terminated if it contains n or more characters.
strcat requires its second argument to be a pointer to a well-formed string. &ipch does not point to a well-formed string (the character sequence of one it points to lacks a terminal null character).
You could use char ipch[2]=" "; to declare ipch. In this case also use:
strcat(ipstr,ipch); to append the character to ipstr.
ipch[0] = intext[j]; to change the character to append.
What happens when you pass &ipch to strcat in your original program is that the function strcat assumes that the string continues, and reads the next bytes in memory. A segmentation fault can result, but it can also happen that strcat reads a few garbage characters and then accidentally finds a null character.
strcat() is to concatenate strings... so passing just a char pointer is not enough... you have to put that character followed by a '\0' char, and then pass the pointer of that thing. As in
/* you must have enough space in string to concatenate things */
char string[100] = "What is the problem";
char *s = "?"; /* a proper '\0' terminated string */
strcat(string, s);
printf("%s\n", string);
strcat function is used to concatenate two strings. Not a string and a character. Syntax-
char *strcat(char *dest, const char *src);
so you need to pass two strings to strcat function.
In your program
strcat(ipstr,&ipch);
it is not a valid statement. The second argument ipch is a char. you should not do that. It results in Segmentation Fault.

Is assignment of strings valid?

Is s1=s2 valid statement? It give me error:
lvalue required
My code:
#include<stdio.h>
#include<conio.h>
void main()
{
char s[1]="integ";
char s[2]="systems";
s1=s2;
printf("%s", s1);
getch();
}
You haven't defined a variable called s2. You have two variables, s1, and s. Also, you can't assign character arrays like that. Declare them as pointers if you need to change the array the variable points to after initialization, or else use strcpy() to copy one string's contents into another (being careful about overflow of course). Finally, you're declaring s with a size of 2, then initializing it with a string that is 7 characters long. Try:
char *s1 = "integ";
char *s2 = "systems";
s1 = s2;
printf(%s", s1);

Resources