String traversal using pointers - c

I am trying to print every fourth character of a string using pointers.
I was able to achieve it using the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[]){
char* string = "WhatTheeHell";
char* p = string;
while(*p != '\0'){
printf("%c\n", *p);
p += 4;
}
return 0;
}
This correctly gives the output to me as:
W
T
H
Now, I tried another way to do it, which according to my knowledge of pointer arithmetic, should have worked, since the size of int on my machine is 4 bytes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[]){
char* string = "WhatTheeHell";
int* p = (int*)string;
while(*p != '\0'){
printf("%c\n", *p);
p += 1;
}
return 0;
}
When I print the output for this, it gives me WTH followed by four newlines.
My question, why are the four newlines being printed? Shouldn't it be that after the H is printed, the *p gives a NULL character present at the end of the string literal and the loop gets terminated?

For starters the first program is invalid. If a string has the number of characters that is not divisible by 4 you will have undefined behavior because the pointer can point to beyond the string using the pointer arithmetic
p += 4;
A valid approach can look the following way as it is shown in the demonstrative program
#include <stdio.h>
int main( void )
{
const char *s = "WhatTheeHell";
const size_t STEP = 4;
if ( *s )
{
const char *p = s;
do
{
printf( "%c\n", *p );
for ( size_t i = 0; i < STEP && *p; ++i, ++p );
} while ( *p );
}
}
Its output is
W
T
H
The second your program is also invalid. For starters it is not necessary thet a string literal is aligned by sizeof( int ) (moreover in general the sizeof( int ) can be greater or less than 4). So the program already has undefined behavior.
In this condition
*p != '\0'
there are compared sizeof( int ) bytes (not a single byte ) with the integer constant '\0'. So the comparison will be always true when the pointer points inside the string (and even beyond the string if there are no zero bytes).
By the way also pay attention to that in C sizeof( '\0' ) is equal to sizeof( int ).

When you compare *p to \0, *p is not a single char but a (presumably) four-byte value (the char is promoted to integer before comparison).
Nothing guaranties that after the \0 of your string there are other zero bytes: this is undefined behaviour.
Thus your loop continues until it reaches by chance a zero integer.
When printing with "%c\n", only the lower byte of the integer is considered; if its value is zero (nothing is guaranteed) it does not print anything visible, just the following \n

Related

Allocate char array and strings

I have problem understanding the code below.
What value index=strlen(strs[0]) gets?
char *a= malloc (sizeof(char)*(index+1)) Is this the standard way to allocate array for char array?
What does strs[i][j] represent?
This is the code I found on leetcode. Just trying to understand the code. (code from sanghi user on leetcode)
#include<string.h>
char* longestCommonPrefix(char** strs, int strsSize)
{
int i=0; int j=0;int index;int tempindex=0;
if(strsSize<1)
return "";
index=strlen(strs[0]);
char *a;
a= malloc(sizeof(char)*(index+1));
strcpy(a,strs[0]);
for(i=1;i<strsSize;i++)
{ tempindex=0;
for(j=0;j<index;j++)
{
if(a[j]==strs[i][j])
tempindex++;
else
{a[j]='\0';
break;
}
}
if (tempindex==0)return ("");
if(tempindex<index)index=tempindex;
}
return a;
}
Expected results can be found on https://leetcode.com/problems/longest-common-prefix/
strs is an array of strings. strsSize is the number of strings in the array.
index = strlen(strs[0]);
This simply gets the length of strs[0], the first string in the array.
a = malloc(sizeof(char)*index+1);
This will allocate enough memory to store a string of the same size. I say enough memory because each string actually has length + 1 characters. The last character is \0, a null terminator. You always have to make sure to terminate your strings or else a bunch of weird buffer overflow stuff can happen.
str[i][j]
This accesses the jth character in the ith string in the array.
For starters the program is bad and invalid.:)
For example the size of the one dimensional array first element of which is pointed to by the parameter strs shall have the type size_t instead of int.
And all other variables that deal with indices also shall have the type size_t as for example
size_t index = strlen( strs[0] );
because the standard C function strlen has the return type size_t.
The source array is not changed in the function so the first parameter shall be declared with the qualifier const.
That is the function declaration shall look like
char * longestCommonPrefix( const char** strs, size_t strsSize);
Farther the elements (strings) of the array can have different lengths, So this loop
for(j=0;j<index;j++)
has undefined behavior because some element (string) of the array can have length less than the value of the variable index.
In fact there is no need to calculate lengths of the elements of the array. The loop can use the condition
for( j=0; j < index && strs[i][j] != '\0'; j++)
And moreover the function has a memory leak due to this return sub-statement in the if statement
a= malloc(sizeof(char)*(index+1));
//...
if (tempindex==0)return ("");
That is the allocated memory pointed to by the pointer a will not released.
What value index=strlen(strs[0]) gets?
index gets the length of the string stored in the first element of the array of strings.
For example if you have an array
char *strs[] = { "Hello", "Bye", "Good Morning" };
then index is set to the length of the string "Hello".
char a= malloc (sizeof(char)(index+1)) Is this the standard way to
allocate array for char array?
Yes in this declaration there is allocated a memory large enough to store the string (including its terminating zero) of the first element of the array pointed to by strs.
What does strs[i][j] represent?
strs[i][j] access j-th character of the i-th element of the array pointed to by strs.
For example for the declaration above strs[0][0] is equal to 'H', strs[0][1] is equal to 'e', strs[1][0] is equal to 'B' and so on.
P.S. A better approach to define the function is the following as it is shown in the demonstrative program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
size_t longestCommonPrefix( const char **strs, size_t strsSize )
{
size_t n = 0;
if ( strsSize != 0 )
{
n = strlen( *strs );
for ( size_t i = 1; n != 0 && i < strsSize; i++ )
{
size_t j = 0;
while ( j < n && strs[i][j] == strs[i-1][j] ) j++;
if ( j < n ) n = j;
}
}
return n;
}
int main(void)
{
char * strs[] = { "0123456789", "012345", "0123" };
size_t n = longestCommonPrefix( ( const char ** )strs, sizeof( strs ) / sizeof( *strs ) );
char *p = NULL;
if ( n != 0 )
{
p = malloc( n + 1 );
memcpy( p, strs[0], n );
p[n] = '\0';
printf( "The longest common prefix is \"%s\"\n", p );
}
free( p );
return 0;
}
The program output is
The longest common prefix is "0123"

How to count non-zero occurrences of a char in C?

I am new in C programming. I would like to ask how I can store a char in a char array? The reason why I want to do it is because I get a char from a computation I make. This computation returns a char consisting of 4. I want to look through every character of the 4 and check if they are "0". If not, then I will increment by one. This is an example of a substitution: "0xf3"- I am trying to compute the Hamming Weight of a substitution. This is how I try to count how many non-zero the char consists of:
#include <stdio.h>
int main()
{
char x = "0xf3";
char s[10] = x;
int lingh = strlen(s);
for (int i = 0; i<lingh;i++) {
printf("%c\n", s[i] );
}
return 0;
}
the output I expect is something like s[] = {0,x,f,3}
This computation returns a char consisting of 4.
You are saying your computation returns a character which consists of 4 characters. Is it possible???
I guess your computation returns a string that consists of 4 characters. Example 0xf3
You can not store a string literal in char type variable.
char x = "0xf3"; //<---------------------
You can store them in a character array like char x[] = "0xf3";
Here is the modified code
#include <stdio.h>
#include<string.h> //<---- for strlen() and strcpy()
int main()
{
char x[] = "0xf3"; //<----store in a char array
char s[10];
strcpy(s, x); //<----copy in another array
int lingh = strlen(s);
for (int i = 0; i<lingh;i++) {
printf("%c\n", s[i] );
}
return 0;
}

Issues with creating a copy of an argument in C

I am converting string arguments into ints I am having an issue where the first argument is not copying and converting to a string while the second argument is working just fine. I am removing the first character of the string array and printing out the rest of the string as an int.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(int argc, char *argv[])
{
char numcpy1[sizeof(argv[1])-1];
char numcpy2[sizeof(argv[2])-1];
int i, len1, len2;
int result1=0;
int result2=0;
//Access first character for base
printf("%c \n", argv[2][0]);
printf("%c \n", argv[3][0]);
//Remove first character for number1 and number 2
if(strlen(argv[2]) > 0)
{
strcpy(numcpy1, &(argv[2][1]));
}
else
{
strcpy(numcpy1, argv[2]);
}
len1 = strlen(numcpy1);
if(strlen(argv[3]) > 0)
{
strcpy(numcpy2, &(argv[3][1]));
}
else
{
strcpy(numcpy2, argv[3]);
}
len2 = strlen(numcpy2);
//Turn remaining string characters into an int
for(i=0; i<len1; i++)
{
result1 = result1 * 10 + ( numcpy1[i] - '0' );
}
for(i=0; i<len2; i++)
{
result2 = result2 * 10 + ( numcpy2[i] - '0' );
}
printf("%d \n", result1);
printf("%d \n", result2);
return 0;
}
Output:
b
b
-4844
1010
What I want:
b
b
1000
1010
The sizeof operator does not give you the length of a string, as you seem to think it does. It tell you the size of the datatype. Since argv[2] is a char *, this evaluates to the size of this pointer, most likely 4 or 8 depending on the system.
If the string in question is longer than this value, you end up writing past the end of the array. This invokes undefined behavior, which in your case manifests as an unexpected result.
If you want the length of the string, use the strlen function instead. Also, you need to add one more byte. Strings in C are null terminated, so you need space for the null byte that marks the end of the string.
char numcpy1[strlen(argv[2])];
char numcpy2[strlen(argv[3])];
Also note that we don't need to add 1 to each of these since the first character in each string isn't copied.
You need to change
char numcpy1[sizeof(argv[1])-1];
to
char numcpy1[strlen(argv[1]) + 1];
Ditto for numcpy2
I think instead of copying the numbers you could work more easily with pointers. Thereby, you don't have to think about memory allocation and copying the values just for the sake of converting them into an integer value:
const char *numcpy1 = argv[2][0]=='\0' ? argv[2] : argv[2]+1;
...

segmentation fault in c while coding Vigenère’s cipher

I am really new to coding and I have been teaching myself how to code by using EDX.org. This week I have been studying about Cryptography and I have to create a Vigenère’s cipher. I wrote the code and for the most part, it's correct. However when I compiled the program, it's showing a segmentation error. I have been trying to figure our why this is happening and I am totally stuck. Could you take a look at my code and tell me whats wrong?
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int index(int k, int c);
int main (int argc, string argv[1])
{
//check for correct criteria
if (argc = 2, isalpha(argv[1]))
{
string text = GetString();
string key = argv[1]; //store key word
int Totalshift = strlen(key); //number of shift for keyword
int shift = 0;
//loops over the whole text
for (int i = 0, n = strlen(text); i <n; i++ )
{
char p= text[i];
char k = toupper(key[shift]); //Upper case for each character
if (isupper(p))
{
//convert to 0 index
p = p - 65;
k = k - 65;
int crypt= index (k , p);
printf("%c", crypt+65);
shift= (shift+1) %Totalshift;
}
else if (islower(p))
{
p = p - 97;
k = k - 65;
int crypt= index (k , p);
printf("%c", crypt+97);
shift= (shift+1) %Totalshift;
}
else
{
printf("%c", p);
}
}
printf("\n");
}
//error message
else
{
printf("ERROR!\n");
return 1;
}
}
//index function
int index(int k, int p)
{
return (k+p)% 26;
}
string
No. Never, ever hide pointers.
int main(int argc, char ** argv)
Then:
//check for correct criteria
if (argc = 2, isalpha(argv[1]))
Here, you assign to the variable (parameters behave like local variables in that respect) the value 2, thus destroying the previous value (which holds the number of arguments given to the program). The result is the value which was assigned, thus 2. Then, there's the comma operator: You discard that 2, and then call isalpha(argv[1]), which clearly shows why you should always turn on warnings and never, ever hide pointers:
argv[1] is of type char *, thus a pointer to a character array (or, as we know in this case, a character array terminated with '\0', which is called a C string). Since isalpha takes an int as parameter the value of the pointer ("the memory address") is implicitly converted to (a probably very large) int value. Quoting from above link, emphasis mine:
The c argument is an int, the value of which the application shall ensure is representable as an unsigned char or equal to the value of the macro EOF. If the argument has any other value, the behavior is undefined.
Which is possibly the source of the segmentation fault.
Finally, that GetString really looks fishy to me. Assuming that it allocates some memory (for the string that it presumably reads from the user) ... where do you free that memory? Is it really allocating memory, or possibly returning a pointer to an array with automatic storage duration (a local variable, so to say)?

Replace a character in char* for double value

I have a char * and I need to replace a character for a double value (unknown number of digits). So I believe that I need to count the number of digits then make a realloc() and replace the characters. I'm just not sure how to count the number of digits and make this replacement.
For example:
char *c = strdup("a+b");
double d = 10;
//I'd like to replace 'a' for 10.
//then 'c' would be : 10+b.
//Next iteration I need to change the 'b' value then I get:
//c = 10 + 3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
const char* s = "a+b";
double d = 10.23142;
//determine the string length needed for printing d
size_t n = snprintf(NULL, 0, "%g", d);
// old string length + n - 1 for replaced b + 1 for '\0'
char* new_s = malloc( strlen(s) + n - 1 + 1);
//write the double
sprintf(new_s, "%g", d);
//skip the first byte (where b is) at the source and the double's length at the destination
strcpy(new_s + n, s + 1);
printf("%s\n", new_s); //prints 10.2314+b
free(new_s);
return 0;
}
It's easy to make an off-by-one error in this kind of pointer arithmetic, so something like gcc's mudflap or AddressSanitizer are really useful in checking to make sure the program doesn't go into undefined behavior in some place.
Better yet, if you can, use C++ and you won't have to worry about this kind of stuff:
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
string s = "a+b";
double d = 10.23142;
s.replace(0,1,to_string(d));
cout<<s<<endl;
return EXIT_SUCCESS;
}
The problem with realloc is that you may not necessarily get back the same address, so technically you may not so much replace the character as create a new string.
You could measure the size of double by printing it into a static buffer, and taking strlen:
char buf[32];
sprintf(buf, "%f", dbl);
size_t Len = strlen(buf);
Demo
Now you can allocate more space, move the content to the back, and then copy characters from buf into reallocated space.

Resources