I was testing the code in GCC in Linux. So far so good, Here is simple SLOC that i tried to achive...
After running the code output is:
<1>
<>
<>
But more impressively when i change order of printf lines giving different results...
What is wrong with this code and about this situation could you please assit me...
Thanks
Regards.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *vbStrReverse(char *pBuffer);
int main(){
printf("<%s>",vbStrReverse("1"));
printf("<%s>",vbStrReverse("123456"));
printf("<%s>",vbStrReverse(""));
}
char *vbStrReverse(char *pBuffer){
int size=strlen(pBuffer);
char *ptr =(char*) malloc(sizeof(char)*size+1);
int i;
int ax;
do
{
ax=*(pBuffer+i);
if (ax=='\0'){
*(ptr+i+1)='\0';
break;
}
*(ptr+i)=*(pBuffer+size-i-1);
i++;
} while (1);
return(ptr);
}
The function has undefined behavior.
For starters the variable i was not initialized
int i;
It seems you mean
int i = 0;
In this statement
*(ptr+i+1)='\0';
a garbage can be included in the array pointed to by the pointer ptr for example when the source string is empty and the memory beyond the allocated array will be overwritten
The function can be declared and defined the following way
char * vbStrReverse( const char *pBuffer )
{
size_t size = strlen( pBuffer );
char *ptr = malloc( size + 1 );
if ( ptr != NULL )
{
ptr += size;
*ptr = '\0';
while ( *pBuffer )
{
*--ptr = *pBuffer++;
}
}
return ptr;
}
Related
There comes an error "conflicting types" so what can I do, and prefer a good alternative for this. The main problem is in returning an array from function
#include<stdio.h>
int* freqofchar(char);
int main()
{
char str[100];
printf("Enter a sentence below :\n");
gets(str);
int* p = freqofchar(str);
for(int i=0;i<128;i++){
if(*p>0){
printf("%c occurred %d times\n",(char) i , *p++);
}
}
return 0;
}
int* freqofchar(char str[]){
int freq[128] = {0};
for(int i = 0;str[i] != '\0';i++){
freq[ str[i] ]++;
}
return freq;
}
You have 2 problems:
1) conflicting types:
int* freqofchar(char)
in declaration, but
int* freqofchar(char str[])
in definition.
2) You are returning freq allocated on stack from freqofchar
The error you see is due to mismatch in the function prototype and its actual definition.
However, you have other problems, too:
gets function has been removed from the C standard (since) for a good reason and should never be used in any case. You can use fgets instead to read input. But you need to remove the newline if fgets reads it in.
You are returning a pointer to a local variable, whose lifetime isn't valid once the function freqofchar returns, which is undefined behaviour. You can instead pass another argument. Generally you may want to consider dynamic allocation (e.g. via malloc) but in this case - you only need a small array - an array local to the main function, which has automatic storage duration and thus its lifetime is valid for the duration of main() and it can be safely passed to freqofchar function without it being invalid or de-allocated as the object's (freq being the object in reference here) lifetime is still valid in when it's being used in freqofchar() - is better-suited here.
Here's how a fixed solution would looks like:
#include<stdio.h>
#include<string.h>
void freqofchar(char*, int*);
int main()
{
char str[100] = {0};
int freq[256] = {0};
printf("Enter a sentence below :\n");
fgets(str, sizeof str, stdin);
/* Remove the newline if present. */
char *p = strchr(str, '\n');
if (p) *p = '\0';
freqofchar(str, freq);
for(size_t i = 0;i < sizeof freq; i++) {
if(freq[i]) {
printf("%c occurred %d times\n", i, freq[i]);
}
}
return 0;
}
void freqofchar(char str[], int freq[])
{
for(int i = 0;str[i] != '\0';i++) {
freq[ str[i] ]++;
}
}
The function parameter is declared in the function declaration as having the type char
int* freqofchar(char);
^^^^^
But in the function declaration that at the same is its definition
int* freqofchar(char str[]){
^^^^^^^^^
the parameter is declared as having the type char [] (that is adjusted by the compiler to the type char *).
This typo is the reason of the compiler message.
But in any case the function shall be declared at least like
unsigned int * freqofchar( const char [] );
That is there is no sense to define frequencies as having signed integer type and the parameter shall have the qualifier const because the passed string is not being changed in the function.
The program has undefined behavior because the function returns pointer to a local array with the automatic storage duration that will not be alive after exiting the function.
int* freqofchar(char str[]){
int freq[128] = {0};
//...
return freq;
}
You should either allocate the array dynamically or declare it with the storage specifier static. In the last case you need to reset elements of the array to zeroes each time when the function is called.
The function gets is an unsafe function and is not supported by the C standard any more. Instead use the standard C function fgets.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned int* freqofchar( const char *);
int main( void )
{
enum { N = 100 };
char str[N];
str[0] = '\0';
printf( "Enter a sentence below : " );
fgets( str, N, stdin );
// remove the appended new line character '\n'
str[ strcspn( str, "\n" ) ] = '\0';
unsigned int *p = freqofchar( str );
for ( size_t i = 0; i < 128; i++ )
{
if ( p[i] )
{
printf( "'%c' occurred %u times\n", ( char )i , p[i] );
}
}
free( p );
return 0;
}
unsigned int * freqofchar( const char str[] )
{
enum { N = 128 };
unsigned int *freq = calloc( N, sizeof( unsigned int ) );
while ( *str ) ++freq[ ( size_t )*str++ ];
return freq;
}
Its output might look like
Enter a sentence below : Hello World!
' ' occurred 1 times
'!' occurred 1 times
'H' occurred 1 times
'W' occurred 1 times
'd' occurred 1 times
'e' occurred 1 times
'l' occurred 3 times
'o' occurred 2 times
'r' occurred 1 times
If to define the function with the static storage specifier then its definition can look the following way.
#include <stdio.h>
#include <string.h>
unsigned int* freqofchar( const char *);
int main( void )
{
enum { N = 100 };
char str[N];
str[0] = '\0';
printf( "Enter a sentence below : " );
fgets( str, N, stdin );
// remove the appended new line character '\n'
str[ strcspn( str, "\n" ) ] = '\0';
unsigned int *p = freqofchar( str );
for ( size_t i = 0; i < 128; i++ )
{
if ( p[i] )
{
printf( "'%c' occurred %u times\n", ( char )i , p[i] );
}
}
return 0;
}
unsigned int * freqofchar( const char str[] )
{
enum { N = 128 };
static unsigned int freq[N];
memset( freq, 0, N * sizeof( unsigned int ) );
while ( *str ) ++freq[ ( size_t )*str++ ];
return freq;
}
You make one of the most common mistakes in the C programming. You return the pointer to the object which does not exist after the function return.
possible solutions
a. use dynamicaly allocated memory
int* freqofchar(char *str)
{
int *freq = malloc(128 * sizeof(*freq)); // or if you want to zero it calloc
/* ... */
return freq;
}
but you need to free the allocated memory when not needed.
b. use static array or global array
int* freqofchar(char *str)
{
static freq[128];
/* ... */
return freq;
}
or
static freq[128];
int* freqofchar(char *str)
{
/* ... */
return freq;
}
Downsides of this solution: the function is not reentrant, the freq array cannot be passed to the async task and functions as it can be changed if function is called again.
The initialisation happens only one time before first call to the function.
c. Wrap it in the union or struct and return the whole object
struct freqstruct {
int freq[128];
};
struct freqstruct freqofchar(char *str)
{
struct freqstruct freq = {0};
/* ... */
return freq;
}
Downside - the whole array wrapped into the struct is copied. It is not very memory and performance wise.
Your definition does not match the declaration of the function. It shows that you did not put enough effort.
int* freqofchar(char *str)
int* freqofchar(char *str)
{
/* ... */
}
or - but I personally do not like this notation as it makes beginners think that the array is passed not the pointer.
int* freqofchar(char str[])
int* freqofchar(char str[])
{
/* ... */
}
This functions is not const corrent - the parameter str should be const char *str or const char str[]
The code below is expected to return a string containing only numbers from an user entered string.
Also the returned string should group the numbers in three digits and put a '-' between them.
Everything runs fine, code compiles without any error, but the char* is not being returned from function.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* phoneNo(char*);
void main(){
char str[100];
char *strpass = str;
printf("Enter the string: ");
fgets(str,100,stdin);
printf("Entered stringis: %s\n",str);
char *result = phoneNo(strpass);
printf("Returned char* is: %s\n",result);
}
char* phoneNo(char *strpass){
char str[100];
strcpy(str,strpass);
printf("Char[] in Function: %s",str);
char answer[100];
char * result;
result = ( char* ) malloc(100*sizeof(char));
result=answer;
//printf("Char* pointed to Char[]: %s\n",result);
int i=0;
int j=0;
int k=3;
while(str[i]!='\0'){
if(str[i]=='1'||str[i]=='2'||str[i]=='3'||str[i]=='4'||str[i]=='5'||str[i]=='6'||str[i]=='7'||str[i]=='8'||str[i]=='9'||str[i]=='0')
{
if(j==0){
answer[j]=str[i];
answer[j+1]='\0';
j++;
i++;
continue;
}
if(j==k){
answer[j]='-';
answer[j+1]='\0';
j++;
k+=4;
}else{
answer[j]=str[i];
answer[j+1]='\0';
j++;
i++;
}
}
else
i++;
}
printf("Char* to be returned: %s\n",result);
return (char *)result;
}
This code snippet
char answer[100];
char * result;
result = ( char* ) malloc(100*sizeof(char));
result=answer;
has a memory leak because the address of the allocated memory is lost due to this statement
result=answer;
Now the pointer result points to the local array answer and returned from the function that results in undefined behavior because the array will not be alive after exiting the function.
Use the allocated dynamically array for processing instead of the local array answer.
Pay attention to that instead of this compound if statement
if(str[i]=='1'||str[i]=='2'||str[i]=='3'||str[i]=='4'||str[i]=='5'||str[i]=='6'||str[i]=='7'||str[i]=='8'||str[i]=='9'||str[i]=='0')
it is much better to write
if ( isdigit( ( unsigned char )str[i] ) )
And the function shall be declared like
char* phoneNo(const char *strpass);
that is its parameter must have the qualifier const.
I would write the function the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char * phoneNo( const char *s )
{
const size_t GROUP_SIZE = 3;
size_t digits_count = 0;
for ( const char *p = s; *p; ++p )
{
if ( isdigit( ( unsigned char )*p ) ) ++digits_count;
}
char *result = malloc( digits_count + digits_count / GROUP_SIZE + sizeof( ( char )'\0' ) );
size_t i = 0;
for ( size_t k = 0; *s; ++s )
{
if ( isdigit( ( unsigned char )*s ) )
{
if ( k == GROUP_SIZE )
{
if ( i != 0 )
{
result[i++] = '-';
}
k = 0;
}
result[i++] = *s;
++k;
}
}
result[i] = '\0';
return result;
}
int main(void)
{
const char *s = "123456789";
char *result = phoneNo( s );
puts( result );
free( result );
s = "12\t34567\t89";
result = phoneNo( s );
puts( result );
free( result );
return 0;
}
The program output is
123-456-789
123-456-789
First you allocate memory for result, then in the next line result=answer; you immediately have it point elsewhere, creating a memory leak while instead pointing at a local variable. This is the bug.
I have a function to update an unsigned char* and cannot find where my bug is. I'm not sure if I need to allocate memory, or if I am pointing to the wrong memory space somewhere. I tried to follow a similar structure as posted here, but have not had success with an unsigned char.
My code so far:
#include <stdio.h>
void changeArray(unsigned char **arr)
{
unsigned char ptr[3] = {100, 101, 102};
*arr = ptr;
printf("%d\n", **(arr+0)); // This prints out the correct value of 100
}
int main(int argc, const char* argv[])
{
int i = 0;
unsigned char *blah;
unsigned char ptr2[3] = {103, 104, 105};
blah = ptr2;
printf("Blah is: \n");
for (i = 0; i < 3; i++) {
printf("%d,",*(blah+i)); //This prints out 103,104,105
}
changeArray(&blah);
printf("Blah is now: \n");
for (i = 0; i < 3; i++) {
printf("%d,", *(blah +i)); //This prints out 0,0,0
}
return 0;
}
Any help in determining how to properly access the values set in the changeArray() function would be greatly appreciated.
With this *arr = ptr; you are storing a pointer to a variable with automatic storage duration. The behaviour undefined.
You can dynamically allocate and return a pointer that way:
void changeArray(unsigned char **arr)
{
unsigned char ptr[3] = {100, 101, 102};
unsigned char *p = malloc(sizeof ptr);
memcpy(p, ptr, sizeof ptr);
*arr = p;
printf("%d\n", **(arr+0)); // This prints out the correct value of 100
}
You should also do error checking if malloc failed and remember to free the allocated memory after use in main.
The problem here is, ptr is local to changeArray() function. So once the function finishes execution, there is no existance of ptr. Hence, once you assign ptr to *arr
*arr = ptr;
and changeArray() execution gets over, accessing blah in main() now will invoke undefined behaviour.
FWIW, you don't need to pass the address of blah, you don't need a pointer-to-pointer at all. blah is already a pointer, which you can pass to changeArray() to alter the contents of the memory area it points to. You can do something like
void changeArray(unsigned char *arr)
{
for (int i = 0; i < 3; i ++)
arr[i] = 100+i;
}
and call it like
changeArray(blah);
This is a practice exam question that I am having some difficulty with:
struct bodytp // Is there an error?
{
char *name; // If so, fix the error.
int len;
};
main()
{
struct bodytp person;
keepname(&person , "Waterman");
printf("%s\n", person.name);
}
void keepname(struct bodytp *onept, const char *last)
{
int len;
char *tpt;
for ( len = 0; last[len] != '\0'; )
len++;
char name[len+1];
for ( tpt = name; *tpt++ = *last++; )
;
onept->name = name;
onept->len = len;
}
I have determined that there is an error, as when I run it, I get garbage output from printf. I have also determined that person's name is indeed "Waterman" after the keepname function call. I have tried dereferencing person.name to person -> name, changing the problem from a stack-based question to a heap-based question by eliminating the ampersand operator and malloc-ing the struct, but nothing worked. Can anyone steer me in the right direction? Thank you in advance.
Is there an error?
struct bodytp // Is there an error?
{
char *name; // If so, fix the error.
int len;
};
No there is no error. It is a valid structure definition.
Now errors follow.:)
Function main shall be declared as
int main( void )
Though it is not an error nevertheless it would be better that before the function call there woud be the function prototype
keepname(&person , "Waterman");
The program has undefined behaviour because there is an assignment of a pointer to the structure by the address of a local array that will be destroyed after exiting the function
void keepname(struct bodytp *onept, const char *last)
{
//...
char name[len+1];
//...
onept->name = name;
//...
}
The valid function could be defined like
void keepname(struct bodytp *onept, const char *last)
{
int len = 0;
char *tpt;
while ( last[len] != '\0' ) len++;
char *name = malloc( len + 1 );
for ( tpt = name; *tpt++ = *last++; ) ;
onept->name = name;
onept->len = len;
}
In this case you have to free the alocated memory in main.
Take into account that you coud use standard C functions strlen and strcpy in the function.
You need to allocate the memory for the name in the heap.
void keepname(struct bodytp *onept, const char *last)
{
int len;
char *tpt;
for ( len = 0; last[len] != '\0';len++);
char *name=malloc(len+1);
onept->name = name;
onept->len = len;
for ( ; *name++ = *last++ ; );
}
Here are the codes of a program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * cloning(char * q){
char s[strlen(q)];
int i;
for(i = 0; i < strlen(q); i++)
s[i] = q[i];
return s;
}
int main(){
char q[] = "hello";
char *s = cloning(q);
return 0;
}
After the compilation a warning appears, so I changed the returned value like this:
char *b = s;
return b;
In this way the warning can be solved. However I found that inside the function cloning(), sizeof(s) is 5, but strlen(s) is 7. And if I change char s[strlen(q)] simply to char s[5], the output is still incorrect. Can anybody explain this problem to me? Thank you very much.
char s[strlen(q)] is a local variable, and hence when you return its address, it results in undefined behaviour. Thus either you could use strdup() or malloc() to dynamically allocate the array, thus ensuring that the array s is available on the heap when you return from the function. The returned array would need to be free()-ed as well, else it would have a memory leak :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * cloning(char * q){
char *s = malloc(strlen(q)+1);
// if you write char s[strlen(q)], it is defined locally, and thus on return gives an undefined behaviour
int i;
for(i = 0; i < strlen(q)+1; i++)
s[i] = q[i];
return s;
}
int main(){
char q[] = "hello";
char *s = cloning(q);
free(s);
return 0;
}
char s[strlen(q)];
is a variable-length array. Like a malloc'ed buffer its size is determined at runtime. Unlike a malloc'ed buffer, it ceases to exist when the function returns.
multiple issues with this code:
char * cloning(char * q){
char s[strlen(q)]; // s has strlen size but needs strlen + 1 to hold \0
int i;
for(i = 0; i < strlen(q); i++) // should copy the \0 otherwise q is not a valid string
s[i] = q[i];
return s;// returns the address of a local var == undef. behavior
}
if you want to clone a string just do strdup()
char* cloning(char* q)
{
return strdup(q);
}
or the equivalent
char * cloning(char * q)
{
char* s = malloc(strlen(q)+1);
int i;
for(i = 0; i < strlen(q)+1; i++)
s[i] = q[i];
return s;
}
The proper way to do this with standard C, no matter version of the C standard, is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* cloning (const char* str)
{
char* clone;
size_t size = strlen(str) + 1;
clone = malloc(size);
if(clone == NULL)
{
return NULL;
}
memcpy(clone, str, size);
return clone;
}
int main(){
char original[] = "hello";
char* clone = cloning(original);
if(clone == NULL)
{
puts("Heap allocation failed.");
return 0;
}
puts(clone);
free(clone);
return 0;
}
Dynamic arrays in C are declared using Malloc and Calloc. Try googling it.
Eg:
char *test;
test = (char *)malloc(sizeof(char)*Multiply_By);
In C,static array is in stack,after function return,it's been destoryed. and string with char has a '\0' end. But strlen don't include it. For example.char q[] = "hello"; strlen(q) = 5,but the real size is 6
If you want to copy a string, the last '\0' must be added at the end.or using
char *s = malloc(sizeof(q)); ...; for(i = 0; i < sizeof(q); i++)
s[i] = q[i];
you also need to free it after using.Maybe become a mem leak.
Hope this can help u.