Printf and Strcpy Bug in C language - c

Here i wrote a piece of code. A function to add long numbers (used strings to represent numbers).
I want to know about two bugs that I usually face while coding in C
About printf statements , sometimes upon removing some printf statements i get logical errors but on putting them back the code runs perfectly. I dont understand why and do let me know how to avoid those errors too.
Eg. In below code, the line mentioned in code (comments specified too infront of that line) after commenting it back or removing it, "Answer" variable receives blank string(case 1) and uncommenting it back gives correct output(case 2)
About strcpy function, what is the bug or analogy in it that it behaves wierd sometimes
Eg. In above mentioned case 2, even though the "add" function is returning correct output why is it not getting copied correctly into the "Answer" variable.
Code is here
#include<stdio.h>
#include<string.h>
char *strrev(char *str)
{
char *p1, *p2;
if (! str || ! *str)
return str;
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
char* add(char a[],char b[]){
int n1=strlen(a);
int n2=strlen(b);
char c[20],d[20];
int i,j,k=0,carry=0,sum=0;
for(i=n1-1,j=n2-1;i>=0 && j>=0;i--,j--){
sum = (a[i]-'0')+(b[j]-'0')+carry;
c[k++]=sum%10 + '0';
carry=sum/10;
}
if(i>=0){
for(;i>=0;i--){
sum = (a[i]-'0')+carry;
c[k++]=sum%10 + '0';
carry=sum/10;
}
}
else if(j>=0){
for(;j>=0;j--){
sum = (b[j]-'0')+carry;
c[k++]=sum%10 +'0';
carry=sum/10;
}
}
if(carry){
while(carry){
c[k++]=carry%10 + '0';
carry/=10;
}
}
c[k]='\0';
printf("\nResult under function = %s",strrev(c)); //upon removing this printf statement the Result variable in main() receives a blank string
return strrev(c);
}
int main(){
char answer[20];
printf("\nAnswer = %s\n",add("0","1"));
strcpy(answer,add("0","1"));
printf("\nNow Answer is %s \n",answer); // Here is the bug
return 0;
}

You have undefined behavior because you return a pointer to a local variable. The array c in the add function will go out of scope once the function returns, leaving you with a stray pointer.

Related

segmentation fault when returning string from function

I was wondering what this code should print. I wanted to check whether it prints we can, can we or we can, but instead i got segmentation fault.
Here is the code:
char* mysubstr() {
char* x = "Yes we can, can we";
char* y = "we can";
char* tmp = x;
while(*tmp) {
if (*tmp == *y)
return *tmp;
tmp++;
}
return x;
}
void main() {
printf("%s", mysubstr());
}
I think the wrong part is the return *tmp;, but why? What's wrong with that?
Your compiler basically already told you what is wrong:
return makes pointer from integer without a cast
This is because you define a function returning a char * but you return a char.
With char *tmp = x; you define a pointer and in your return statement you dereference it.
Hence you return (char*)'w'
If you use that return value for printf value 'w' is taken an address which causes your crash.
You should just do return tmp;
This is not the only issue in your code.
Your function name indicates you want to make some substring function.
Bur your code returns immediately it found a match of first letter in second string. You don't verify if the other character also are same.
Following works:
char* mysubstr()
{
char* x = "Yes we can, can we";
char* y = "we can";
char* tmp = x;
while(*tmp)
{
if(*tmp == *y)
{
return (char*) tmp;
}
tmp++;
}
return (char*) x;
}
int main()
{
printf("%s", mysubstr());
return 0;
}
And the answer is:
**We can, can we**

C string recursive function to find out equality from middle

i feel kinda lost, since we started learning about pointers i kinda cant follow and i know its really important subject in C.
anyway!
so i got to make a recursive function, that will get 2 pointers:
1) pointer to index [0].
2) pointer 2 to the middle of the string.
now.. i gotta check if the first part from 0 to middle is equal from middle to end. like..... ADAMADAM.
before i transfer the string i changed entire lower letters to capitals to avoid case sensitivity... so i got something like this.. but its refusing to work.
also using constant is prohibited...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define SS 81
int CheckString(char *,int *);
int main() {
char str[SS];
int length,len,strcheck;
printf("Please enter a string:\n");
fgets(str,SS,stdin);
len=(strlen(str) - 1);
if((len>0)&&(str[len]=='\n')) // replacing '\n' key to '\0'
str[len]='\0';
length=len/2;
strcheck=CheckString(str,&length);
if (strcheck==FALSE)
printf("FALSE.\n");
else
printf("TRUE.\n");
return 0;
}
// function
int CheckString(char *str, int *i) {
if (*str != '\0')
if (*str == str[*i])
return CheckString(str+1,i++);
else
return FALSE;
return TRUE;
}
so i guess i got some problem with the pointers
It seems you mean the following
#include <stdio.h>
#include <string.h>
int CheckString(const char *s, size_t *i)
{
return s[*i] == '\0' || *s == s[*i] && CheckString(s + 1, i);
}
int main( void )
{
char *s = "ADAMADAM";
size_t i = strlen(s) / 2;
int result = CheckString(s, &i);
printf("%s\n", result ? "true" : "false");
return 0;
}
The program output
true
Note: maybe you should calculate the value for the second argument the following way
size_t i = ( strlen(s) + 1 ) / 2;
Think about this.
The outer condition in the loop inside CheckString() should be checking for *(str + *i) != '\0', or equivalently, for str[*i] != '\0'. Also, you do not need to increment *i, and certainly not i, since that is a pointer. The value *i is the distance between the characters being checked in the two halves of the string.
The modified function could look like:
int CheckString(char *str, int *i) {
if (str[*i] != '\0') {
if (*str == str[*i]) {
return CheckString(str+1,i);
} else {
return FALSE;
}
}
return TRUE;
}
The problem specification says (more or less):
I've got to make a recursive function that will get 2 pointers:
pointer 1 to index [0].
pointer 2 to the middle of the string.
I've got to check if the first part from 0 to middle is equal to the second part from middle to end, like: ADAMADAM.
As an exercise in recursion, this is fine; as a way of implementing the functionality, recursion is overkill (iteration is fine).
There is confusion (ambiguity) about the interface to the function — the wording of the question seems to suggest two char * values, but the code uses a pointer to an integer as the second argument. That's singularly peculiar. An integer value could make sense, but a pointer to an integer does not.
We need to define the conditions carefully. Taking the example string given (char str1[] = "ADAMADAM";), the two pointers might be char *p1 = &str1[0]; char *p2 = &str1[0] + strlen(str1) / 2; — meaning p1 points to the first A and p2 to the third A. Consider an alternative string: char str2[] = "MADAMADAM";; The equivalent formula would leave p1 pointing at the first M and p2 pointing at the second M.
Assuming p1 and p2 are incremented in lock-step, then:
The strings are different if, at any point before *p2 equals '\0', *p1 != *p2.
If *p2 equals '\0', then the strings are the same.
By definition, p1 and p2 point to the same array, so pointer differences are legitimate.
Further, p1 must be less than p2 to be useful; p1 equal to p2 means the strings are identical trivially.
There is a strong argument that the 'middle of the string' criterion means that either p2[p2 - p1] == '\0' or p2[p2 - p1 + 1] == '\0' (for even and odd string lengths respectively). That is, the distance between the two pointers indicates where the end of the string must be. It means that using p1 = &str[0] and p2 = &str[2] (on either of the sample strings) should fail because the end of string isn't in the right place. And if the string was "AMAMAMAM", using &str[0] and &str[2] should fail because the end of string isn't in the right place; ditto &str[0] and &str[6].
However, this 'strong argument' is also a design decision. It would be feasible to simply demand that the substring from p2 to EOS (end of string) is the same as the string from p1 for the same length. In that case, using &str[0] with either &str[2] or &str[6] (or, indeed, with the normal &str[4]) on "AMAMAMAM" would work fine.
Using some of these observations leads to this code. If you're really under instructions not to use const, simply remove the const qualifiers where they appear. The code will work the same.
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
static bool identical_halfstrings(const char *p1, const char *p2)
{
assert(p1 <= p2);
assert(strlen(p1) >= strlen(p2) + (p2 - p1));
if (*p2 == '\0')
return true;
if (*p1 != *p2)
return false;
return identical_halfstrings(p1+1, p2+1);
}
int main(void)
{
const char *strings[] =
{
"ADAMADAM",
"MADAMADAM",
"nonsense",
};
enum { NUM_STRINGS = sizeof(strings) / sizeof(strings[0]) };
for (int i = 0; i < NUM_STRINGS; i++)
{
const char *p1 = strings[i];
const char *p2 = strings[i] + strlen(strings[i]) / 2;
printf("[%s] ([%s]) = %s\n", p1, p2,
identical_halfstrings(p1, p2) ? "TRUE" : "FALSE");
}
return 0;
}
The second assertion ensures that p1 and p2 are pointing to the same string — that there isn't a null byte between the locations pointed at by p1 and p2.
Test case output:
[ADAMADAM] ([ADAM]) = TRUE
[MADAMADAM] ([MADAM]) = TRUE
[nonsense] ([ense]) = FALSE
Just for the record, an iterative version of the same function is:
static bool identical_halfstrings(const char *p1, const char *p2)
{
assert(p1 <= p2);
assert(strlen(p1) >= strlen(p2) + (p2 - p1));
while (*p2 != '\0')
{
if (*p1++ != *p2++)
return false;
}
return true;
}
It produces the same output for the sample data.

Extracting web addresses from a string in C

I have trouble with my code and I need your help! What I need to do is to write a function that will extract the web address that starts from www. and ends with .edu from an inputted string. The inputted string will have no spaces in it so scanf() should work well here.
For example:
http://www.school.edu/admission. The extracted address should be www.school.edu.
This is what I came up with so far, it obviously didn't work, and I can't think of anything else unfortunately.
void extract(char *s1, char *s2) {
int size = 0;
char *p, *j;
p = s1;
j = s2;
size = strlen(s1);
for(p = s1; p < (s1 + size); p++) {
if(*p == 'w' && *(p+1) == 'w' && *(p+2) == 'w' && *(p+3) == '.'){
for(p; p < (p+4); p++)
strcat(*j, *p);
}
else if(*p=='.' && *(p+1)=='e' && *(p+2)=='d' && *(p+3)=='u'){
for(p; (p+1) < (p+4); p++)
strcat(*j, *p);
}
}
size = strlen(j);
*(j+size+1) = '\0';
}
The function has to use pointer arithmetic. The errors I get have something to do with incompatible types and casting. Thanks ahead!
So the most trivial approach might be:
#include <stdio.h>
int main(void)
{
char str[1000];
sscanf("http://www.school.edu/admission", "%*[^/]%*c%*c%[^/]", str);
puts(str);
}
Now, here goes the fixed code:
#include <stdio.h>
#include <string.h>
void extract(char *s1, char *s2) {
size_t size = strlen(s1), i = 0;
while(memcmp(s1 + i, "www.", 4)){
i++;
}
while(memcmp(s1 + i, ".edu", 4)){
*s2++ = *(s1 + i);
i++;
}
*s2 = '\0';
strcat(s2, ".edu");
}
int main(void)
{
char str1[1000] = "http://www.school.edu/admission", str2[1000];
extract(str1, str2);
puts(str2);
}
Note that s2 must be large enough to contain the extracted web address, or you may get a segfault.
This is an easy solution for your problem:
char* extract(char *s1) {
char* ptr_www;
char* ptr_edu;
int len ;
char* s2;
ptr_www = strstr(s1,"www");
ptr_edu = strstr(s1,".edu");
len = ptr_edu -ptr_www + 4;
s2 = malloc (sizeof(char)*len+1);
strncpy(s2,ptr_www,len);
s2[len] = '\0';
printf ("%s",s2);
return s2;
}
There is a lot wrong unfortunately. Your compilation is failing because you pass a char to strcat when it expects a char*. Even if it did compile though it would crash.
for(p = s1; p < (s1 + size); p++) {
// This if statement will reference beyond s1+size when p=s1+size-2. Consequently it may segfault
if(*p=='w' && *(p+1)=='w' && *(p+2)=='w' && *(p+3)=='.') {
for(p; p < (p+4); p++) // This is an infinite loop
// strcat concatenates one string onto another.
// Dereferencing the pointer makes no sense.
// This is the likely causing your compilation error.
// If this compiled it would almost certainly segfault.
strcat(*j, *p);
}
// This will also reference beyond s1+size. Consequently it may segfault
else if(*p=='.' && *(p+1)=='e' && *(p+2)=='d' && *(p+3)=='u') {
for(p; (p+1) < (p+4); p++) // This is also an infinite loop
// Again strcat expects 2x char* (aka. strings) not 2x char
// This will also almost certainly segfault.
strcat(*j, *p);
}
}
// strlen() counts the number of chars until the first '\0' occurrence
// It is never correct to call strlen() to determine where to add a '\0' string termination character.
// If the character were actually absent this would almost certainly result in a segfault.
// As it is strcat() (when called correctly) will add the terminator anyway.
size = strlen(j);
*(j+size+1) = '\0';
EDIT: This seems like a homework question, so I thought it would be more constructive to mention where your current code is going wrong, so you can recheck your knowledge in those areas.
The answer to your exact question is it doesn't compile because you dereference the string and hence pass 2x char instead of char* to strcat().

What line is at fault -- segfault, that is...?

I'm relatively new to C (and completely new to StackOverflow - hey guys!), and this segfault has been giving me no surcease of sorrow for the past few hours (DevC++ on a windows machine). It's just a simple palindrome prime program, but it's really giving me a hard time. I'm not generally a novice programmer like it seems here, but... Good god. Now I remember why I wanted to get away from C++ and to Python so quickly.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
FILE *outputFile;
char buffer[81];
char* strrev();
int bytesWritten;
char* strI = 0;
char *strrev(char str[])
{
char *p1 =NULL;
char *p2 =NULL;
if (! str || ! *str)
return str;
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
main()
{
int isPrime(int);
int i,j;
outputFile = fopen("DD:OUTPUT", "w");
if (outputFile == NULL)
{
printf("open error: %d/%s\n", errno, strerror(errno));
exit(99);
}
for (i=1; i<15000; i++)
{
if (isPrime(i)==1)
{
bytesWritten = sprintf(buffer,"%d is primepal!\n",i);
fwrite(buffer, 1, bytesWritten, outputFile);
}
}
fclose(outputFile);
return 0;
}
int isPrime(int myInt)
{
int loop;
for (loop = 2; loop < myInt/2+1; loop++)
sprintf(strI, "%s%d", 10, myInt);
{
if (myInt%loop==0 && (atoi(strrev(strI))-myInt)==0)
{
return 0;
}
return 1;
}
}
I apologize ahead of time if this is a dumb question, and the answer is very obvious -- but I've officially hit the limit where no matter how logical an answer, I've been coding the same problem for too long for it to make any sense. And also, segfaults are horrible beasts. Thank you ahead of time for anything you have to offer!
~ Jordan
The line sprintf(strI, "%s%d", 10, myInt); is likely crashing.
You have not allocated any space for strI, it's defined as char* strI = 0; Make it a char[64] , or a suitable size.
You're giving the wrong arguments to sprintf, "%s%d" says the first parameter should be a string ("%s") , but you give it an int. Change %s to %d
Some other issues:
Don't use *p1 ^= *p2; hack to to swap variables, there's many cases where this does not work. Do it properly with a temp variable.
main() calls isPrime(), but there's no prototype for isPrime at that time. Place int isPrime(int myInt); somewhere before main().
The prototype for your strrev function should be char *strrev(char str[]); and not char *strrev()
Segfaults don't have to be as bad as you're experiencing. Compile the program with debugging symbols (add -g to gcc) and run it in gdb. After the segfault, type bt in gdb and press enter. It will tell you the exact line of your segfault.
for (loop = 2; loop < myInt/2+1; loop++)
sprintf(strI, "%s%d", 10, myInt);
{
if (myInt%loop==0 && (atoi(strrev(strI))-myInt)==0)
You might want to double-check where you've got that brace in relation to the for. This isn't python, and indentation alone doesn't cut it.

printf() statement makes a difference to my return value? - C Programming

I'm experimenting with one of the functions in the K&R C Programming Language book and using pointers to write the strindex function rather than array notation. I have a strange problem that if I include a printf() statement at either of the two points in my code below then the function returns the correct index (6 in this case), but if I leave the printf() statements out then the function returns -1.
I really can't see why this should make any difference at all and would be grateful for any clarification. Here's my code:
#include <stdio.h>
int strindex(char *a, char *b) {
char *pa;
char *astart = a;
char *pb = b;
int len;
while(*pb++ != '\0')
len++;
while(*a != '\0') {
pa = a;
pb = b;
for(;*pb != '\0' && *pa == *pb; pa++, pb++)
;
if(len > 0 && *pb == '\0') {
return a - astart;
}
//printf("%c\n", *a);
a++;
}
//printf("%c\n", *a);
return -1;
}
int main() {
char *a = "experiment";
char *b = "me";
printf("index is %d\n", strindex(a, b));
return 0;
}
Many thanks
Joe
The problem is the automatic variable len. Since you don't initialize it, it starts with a indeterminate (garbage) value. Then you increment it, so it will end up as 'garbage + length of b'. Any single change to the compiled code, like an extra printf call can change the starting value of len and thus change the behaviour of your program.
The solution: int len = 0;, and see if you can get more warnings from your compiler. If you are using gcc, use the -O -Wall -Wextra flags. Then you should get a warning like:
strindex.c:8: warning: ‘len’ may be used uninitialized in this function

Resources