I have to compare few characters of string say from 2nd char till 4th character( counting starts from zero)
The string is stored in elements of structure say zoopla->real
for example zoopla ->real has '447889036' where real is of type char real[20];
Also please note I cant use function strnstr.
The code works as expected but just for curiousity, I have added printf statement and it shows me value till 4th cahr and then some garabe characters.
I want to know why the printf statment is showing 2 extra garabe values?
char * copyTemp;
char *strptr;
copyTemp = (char *)malloc(sizeof(char)*6);
strncpy(copyTemp, zoopla->real, 5);
printf("the string copied is %s", copyTemp); // debug statemnt
strptr = strstr(copyTemp, "666");
if(strptr != NULL)
{
//some other function
}
else
//some other function
free(copyTemp);
All criticism and suggestions are welcome
It seems to me that copyTemp is not null terminated. That's why printf shows you garbage characters after the characters you put in there. It doesn't know where to stop so it continues iterate through memory.
Add
copyTemp[5] = '\0';
after strncpy.
See this example from the documentation of strncpy:
/* strncpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]= "To be or not to be";
char str2[6];
strncpy (str2,str1,5);
str2[5]='\0';
puts (str2);
return 0;
}
see
http://www.cplusplus.com/reference/clibrary/cstring/strncpy/
No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.
you have to add null your self.
if you will be allocating memory of constant size then use array only.
#include <stdio.h>
#include <string.h>
int main ()
{
char * copyTemp;
char *strptr;
copyTemp = (char *)calloc(sizeof(char),6);
strncpy(copyTemp, "88666782921", 5);
printf("the string copied is %s", copyTemp); // debug statemnt
strptr = strstr(copyTemp, "666");
if(strptr != NULL)
{
//some other function
}
else
//some other function
free(copyTemp);
return 0;
}
According to my old K&R, strncpy will only implicitly add null bytes if the source string has fewer characters than the number to be copied.
In this case, zoopla->real has more than 5 characters, so the function is simply copying the first five characters. Since you haven't initialized the memory to zero, or explicitly added a null byte, the string is not terminated after the fifth character. So when you print the string, you get additional bytes with essentially random values, until one is hit that happens to be zero.
Related
Problem Statement
Today is Newton School's first class of this year. Nutan, a student at
Newton School, has received his first assignment. He will be given a
string as input. His task is to print "Gravity'' if the input is
"Apple''; otherwise, he will have to print "Space''.
Can you help Nutan in solving his first assignment? Note that the
quotation marks are just for clarity. They are not part of the input
string, and should not be a part of your output string. Input The
input consists of a single line that contains a string S (1 ≤ length
of S ≤ 10). The string only consists of lowercase and uppercase
letters. Output Print "Gravity'' or "Space'' according to the input.
What I am trying to do:
Basically, I am taking a user-defined string and trying to compare it with the hard input string i.e "Apple". If both the string matches then it will print "Gravity" or else it will print "Space"
#include <stdio.h> // header file for Standard Input Output
#include <stdlib.h> // header file for Standard Library
#include <string.h> // for strcmp() function
int main() {
char str1[10]="Apple";
char str2[20];
int value;
printf("Enter the input ");
scanf("%s", &str2[20]);
value = strcmp(str1, str2);
if(value==0)
printf("Gravity");
else
printf("Space");
return 0;
}
scanf("%s", &str2[20]);
may invoke undefined behavior by out-of-range access. You should:
Pass the pointer to the first element of the array, not one to the next element of the last element. (most) arrays in expressions are automatically converted to pointes to their first elements.
Specify the maximum length to read to avoid buffer overrun.
Check if reading succeeded.
The line should be:
if (scanf("%19s", str2) != 1) {
puts("read error");
return 1;
}
Some improvements:
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
always check whether scanf() input was successful or not
Use const char * instead of char str1[10]
There's no need for int value;
SYNTAX ERROR: &str2[20]
There's no need for passing the address of str2 READ MORE
Initialize str2 with zeroes
Add 1 more space in your str2 for NULL ('\0') terminating character
Final Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *str1 = "Apple";
char str2[21] = {};
printf("Enter the input ");
if(scanf("%20s", str2) != 1)
{
fprintf(stderr, "bad input\n");
return EXIT_FAILURE;
}
if(strcmp(str1, str2) == 0)
printf("Gravity");
else
printf("Space");
return EXIT_SUCCESS;
}
You are entering a string starting from the memory address after the last element of the array str2
scanf("%s", &str2[20]);
and then trying to compare the character array str1 with the non-initialized array str2
value = strcmp(str1, str2);
Change the call of scanf like
scanf("%19s", str2);
And the program will be safer if at least the array str2 will be initially initialized
char str2[20] = "";
Also as the array str1 is not changed then instead of the array you could declare a pointer to the string literal like
const char *str1 = "Apple";
And instead of the calls of printf
printf("Gravity");
//..
printf("Space");
it is better to use calls of puts
puts("Gravity");
//..
puts("Space");
Pay attention to that neither declaration from the header <stdlib.h> is used in your program. So you may remove this include directive
#include <stdlib.h> // header file for Standard Library
#include <stdio.h>
#include <string.h>
int main()
{
char *str3;
str3="Final string.";
for(;*str3;)
{
printf("%c", *str3++);
}
printf("\n");
printf("%d bytes", strlen(str3));
return 0;
}
I've been confused about why the output says 0 bytes when it should be saying 13 bytes. I removed the for loop like so:
#include <stdio.h>
#include <string.h>
int main()
{
char *str3;
str3="Final string.";
printf("%d bytes", strlen(str3));
return 0;
}
and the output comes out correct saying 13 bytes. So I figured it had something to do with the for loop. My guess was: The loop reads through the contents but updates the variable as it goes along i.e. *str3++, once it's complete there's no data left to read and all the data that was already read is, well, read & gone (hehe)... which means 0 bytes?? Like reading a book and whiting out the last word you read.
If that's the case I'd have to refill it with data, do a repeat initialization by putting str3="Final string."; directly after the for loop and it'll show the correct output...but...I feel like that's a bad/cheap trick?
I'm not exactly sure what's happening. Please help.
Thanks in advance!!
Before for loop, str3 is pointing to:
str3
|
V
+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
|F|i|n|a|l| |s|t|r|i|n|g|.|\0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
In for loop you are incrementing str3 in printf() till str3 hits null-character:
printf("%c", *str3++);
So, after for loop str3 is pointing to:
str3
|
V
+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
|F|i|n|a|l| |s|t|r|i|n|g|.|\0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
strlen() determines the length of a string by terminating null-character. Since str3 is pointing to terminating null-character of string, hence you are getting the output 0.
You can take another pointer and point it to str3 and use it in for loop, like this:
#include <stdio.h>
#include <string.h>
int main()
{
char *str3, *tmp;
str3="Final string.";
tmp=str3;
for(;*tmp;)
{
printf("%c", *tmp++);
}
printf("\n");
printf("%zu bytes", strlen(str3));
return 0;
}
Output:
Final string.
13
Additional:
strlen() return type is size_t. You should use format specifier %zu for printing the strlen returned value.
You are incrementing the str pointer until it points to 0 (the end of the string) and when you call strlen(str3) it returns 0.
you are advancing the pointer to the start (initialization)of the string until it points to the end of the string. Hence when you call strlen on it you get size 0 - at that point it already points to the end of the string
you should use an auxillary pointer to iterate the string - advance it while iterating while the strlen command will be with the original str3
you can also add a counter in your for body and that will save you the need to call strlen at the end
in your case the string is literal and does not need to be freed, but when the strings are dynamically allocated working with an auxillary pointer is a must. - you must free allocated memory with the original pointer (returned from the allocation)
I am trying to concatenate two strings in C and receive a "Thread 1: signal SIGABRT" error.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
int main() {
char name[50];
ifile = fopen("stats.list", "r");
for(;;) {
fscanf(ifile, "%s%f%f", name, &sky, &stddev);
if (feof(ifile))
break;
char ext[5] = ".par";
dataparsFile = strcat(name, ext);
dataparsFile = fopen(dataparsFile, "w");
fprintf(dataparsFile, "%s\n",
"stuff gets read in to file named after new string";
fprintf(ofile, "phot ");
fprintf(ofile, "%s%s%s%s%s%s \n",
", datapars=", dataparsFile);
}
fclose(ifile);
fclose(ofile);
The goal of the code is to take an image name that is read in and add on the .par extension. Then, I want to open a file with that name of image+.par and write into it. Since I will have a couple hundred such files, I need to loop through them with the name changing each time.
The problem is name is not initialized. You see, in c strings use a convention, they are any sequence of ASCII (probably some other printable characters, but in principle just ASCII) that must be followed by a '\0' byte that marks the end of the string.
Your name array doesn't have this '\0' so strcat() tries to find it but it fails and perhaps it reads beyond the end of the array, although anyway reading uninitialized data is undefined behavior.
The way strcat(dst, src) works is pretty much like this
char *
strcat(char *const dst, char *src)
{
// Make a pointer to keep dst's address
// unchanged and return it
char *ptr = dst;
// Compute search for the end of the destination
// string to start copying there
while (*ptr != '\0')
ptr++;
// Copy all the characters from `src' until the '\0'
// occurs
while (*src != '\0')
*(ptr++) = *(src++);
*ptr = '\0';
return dst;
}
As you see, this is very inefficient if you call strcat() many times, and it will certainly not work if you pass either of the parameters before initializing it.
In fact, it's terribly unsafe because there is no bound checking, the caller has to make sure that the destination array is large enough to hold both strings.
I'm new to C and pointers, so i have this problem. I want to tell to pointer how much memory it should point to.
char * pointer;
char arr[] = "Hello";
pointer = arr;
printf("%s \n", pointer);
This pointer will point to whole array, so i will get "Hello" on the screen. My question is how can i make pointer to only get "Hel".
You may try this:
char * pointer;
char arr[] = "Hello";
pointer = arr;
pointer[3] = '\0'; // null terminate of string
printf("%s \n", pointer);
If you always work with strings, then have a look at strlen for getting length of a string. If a string arr has length l, then you may set arr[l/2] = '\0', so that when you print arr, only its first half will be shown.
You may also want to print the last half of your string arr? You can use pointer to point to any place you want as the start. Back to your example, you may try:
char * pointer;
char arr[] = "Hello";
pointer = arr + 2; // point to arr[2]
printf("%s \n", pointer);
Have a check what you will get.
printf has the ability to print less than the full string, using the precision value in the format string. For a fixed number of characters (e.g. 3), it's as simple as
printf( "%.3s\n", pointer );
For a variable number of characters, use an asterisk for the precision, and pass the length before the pointer
int length = 3;
printf( "%.*s\n", length, pointer );
You don't know what a pointer is so I'll explain.
A pointer does not point to a string. It points to a char! Yes, a char. A string in C is really just a set of chars all one after the other in the memory.
A char* pointer points to the beginning of a string. The string ends when there is a '\0' (aka null) char. When you printf("%s",s), what printf does is a cycle like this:
int i;
for(i=0;1;i++) //infinite cycle
{
if(s[i]=='\0')
break;
printf("%c",s[i]);
}
Meaning it will not print a string but all the chars in a char array until it finds a null char or it goes into memory space that is not reserved to it (Segmentation fault).
To print just the 1st 3 characters you could do something like this:
void printString(char* s,int n) //n=number of characters you want to print
{
if(n>strlen(s))
n=strlen(s);
else if(n<0)
return;
char temp=s[n]; //save the character that is in the n'th position of s (counting since 0) so you can restore it later
s[n]='\0'; //put a '\0' where you want the printf to stop printing
printf("%s",s); //print the string until getting to the '\0' that you just put there
s[n]=temp; //restore the character that was there so you don't alter the string
}
Also, your declaration of pointer is unnecessary because it is pointing to the exact same position as arr. You can check this with printf("%p %p\n",arr,pointer);
How much of the string is printed is controlled by the NULL-character "\0", which C automatically appends to every string. If you wish to print out just a portion, either override a character in the string with a "\0", or use the fwrite function or something similar to write just a few bytes to stdout.
You could achieve the objective with a small function, say substring.
#include<stdio.h>
#include<string.h> // for accessing strlen function
void substring(char* c,int len)
{
if (len <= strlen(c)){
*(c+len)='\0';
printf("%s\n",c);
}
else{
printf("Sorry length, %d not allowed\n",len);
}
}
int main(void)
{
char c[]="teststring";
char* ptr=c;
substring(ptr,4); // 4 is where you wish to trim the string.
return 0;
}
Notes:
In C++ a built-in function called substring is already available which shouldn't be confused with this.
When a string is passed to a function like printf using a format specifier %s the function prints all the characters till it reaches a null character or \0. In essence, to trim a string c to 4 characters means you put c[4] to null. Since the count starts from 0, we are actually changing the 5th character though. Hope the example makes it more clear.
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.