How to iterate over a string in C? - c

Right now I'm trying this:
#include <stdio.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: %s %s sourcecode input", argv[0], argv[1]);
}
else {
char source[] = "This is an example.";
int i;
for (i = 0; i < sizeof(source); i++) {
printf("%c", source[i]);
}
}
getchar();
return 0;
}
This does also NOT work:
char *source = "This is an example.";
int i;
for (i = 0; i < strlen(source); i++){
printf("%c", source[i]);
}
I get the error
Unhandled exception at 0x5bf714cf (msvcr100d.dll) in Test.exe: 0xC0000005: Access violation while reading at position 0x00000054.
(loosely translated from german)
So what's wrong with my code?

You want:
for (i = 0; i < strlen(source); i++) {
sizeof gives you the size of the pointer, not the string. However, it would have worked if you had declared the pointer as an array:
char source[] = "This is an example.";
but if you pass the array to function, that too will decay to a pointer. For strings it's best to always use strlen. And note what others have said about changing printf to use %c. And also, taking mmyers comments on efficiency into account, it would be better to move the call to strlen out of the loop:
int len = strlen(source);
for (i = 0; i < len; i++) {
or rewrite the loop:
for (i = 0; source[i] != 0; i++) {

One common idiom is:
char* c = source;
while (*c) putchar(*c++);
A few notes:
In C, strings are null-terminated. You iterate while the read character is not the null character.
*c++ increments c and returns the dereferenced old value of c.
printf("%s") prints a null-terminated string, not a char. This is the cause of your access violation.

Rather than use strlen as suggested above, you can just check for the NULL character:
#include <stdio.h>
int main(int argc, char *argv[])
{
const char *const pszSource = "This is an example.";
const char *pszChar = pszSource;
while (pszChar != NULL && *pszChar != '\0')
{
printf("%s", *pszChar);
++pszChar;
}
getchar();
return 0;
}

An optimized approach:
for (char character = *string; character != '\0'; character = *++string)
{
putchar(character); // Do something with character.
}
Most C strings are null-terminated, meaning that as soon as the character becomes a '\0' the loop should stop. The *++string is moving the pointer one byte, then dereferencing it, and the loop repeats.
The reason why this is more efficient than strlen() is because strlen already loops through the string to find the length, so you would effectively be looping twice (one more time than needed) with strlen().

sizeof(source) returns the number of bytes required by the pointer char*. You should replace it with strlen(source) which will be the length of the string you're trying to display.
Also, you should probably replace printf("%s",source[i]) with printf("%c",source[i]) since you're displaying a character.

sizeof() includes the terminating null character. You should use strlen() (but put the call outside the loop and save it in a variable), but that's probably not what's causing the exception.
you should use "%c", not "%s" in printf - you are printing a character, not a string.

This should work
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char *source = "This is an example.";
int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation
for (int i = 0; i < length; i++)
{
printf("%c", source[i]);
}
}

The last index of a C-String is always the integer value 0, hence the phrase "null terminated string". Since integer 0 is the same as the Boolean value false in C, you can use that to make a simple while clause for your for loop. When it hits the last index, it will find a zero and equate that to false, ending the for loop.
for(int i = 0; string[i]; i++) { printf("Char at position %d is %c\n", i, string[i]); }

sizeof(source) is returning to you the size of a char*, not the length of the string. You should be using strlen(source), and you should move that out of the loop, or else you'll be recalculating the size of the string every loop.
By printing with the %s format modifier, printf is looking for a char*, but you're actually passing a char. You should use the %c modifier.

Just change sizeof with strlen.
Like this:
char *source = "This is an example.";
int i;
for (i = 0; i < strlen(source); i++){
printf("%c", source[i]);
}

This is 11 years old but relevant to someone who is learning C. I don't understand why we have all this discussion and disagreement about something so fundamental. A string literal in C, I.E. "Text between quotes" has an implicit null terminator after the last character. Don't let the name confuse you. The null terminator is equal to numeric 0. Its purpose is exactly what OP needs it for:
char source[] = "This is an example.";
for (int i = 0; source[i]; i++)
printf("%c", source[i]);
A char in C is an 8-bit integer with the numeric ASCII value of the corresponding character. That means source[i] is a positive integer until char[19], which is the null terminator after the final '.' The null character is ASCII 0. This is where the loop terminates. The loop iterates through every character with no regard for the length of the array.

Replace sizeof with strlen and it should work.

sizeof(source) returns sizeof a pointer as source is declared as char *.
Correct way to use it is strlen(source).
Next:
printf("%s",source[i]);
expects string. i.e %s expects string but you are iterating in a loop to print each character. Hence use %c.
However your way of accessing(iterating) a string using the index i is correct and hence there are no other issues in it.

You need a pointer to the first char to have an ANSI string.
printf("%s", source + i);
will do the job
Plus, of course you should have meant strlen(source), not sizeof(source).

Related

How to return empty string from a function in C?

How should I return an empty string from a function? I tried using lcp[i] = ' ' but it creates an error. Then I used lcp[i] = 0 and it returned an empty string. However, I do not know if it's right.
Also, is it necessary to use free(lcp) in the caller function? Since I could not free and return at the same time.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 50
char *find_LCP(char str1[], char str2[]);
char *find_LCP(char str1[], char str2[]){
char * lcp = malloc(MAX_LEN * sizeof(char));
int a = strlen(str1);
int b = strlen(str2);
int min = a < b ? a : b;
for(int i = 0; i < min; i++){
if(str1[i] == str2[i])
lcp[i] = str1[i];
else
lcp[i] = 0;
}
return lcp;
}
int main()
{
char str1[MAX_LEN], str2[MAX_LEN];
char * lcp;
printf("Enter first word > ");
scanf("%s", str1);
printf("Enter second word > ");
scanf("%s", str2);
lcp = find_LCP(str1, str2);
printf("\nLongest common prefix: '%s'\n", lcp);
free(lcp);
return 0;
}
An "empty" string is just a string with the first byte zero, so you can write:
s[0] = 0;
However, it is not clear what you are trying to do. The LCP of "foo" and "fob" is "fo", not the empty string.
You can also return as soon as you find the first non-matching character, no need to go until the end.
Further, you can simply pass the output string as a parameter and have lcp be an array. That way you avoid both malloc and free:
char lcp[MAX_LEN];
...
find_LCP(lcp, str1, str2);
If you want to empty a string without using a for loop then you can do
lcp[0] = 0
but for emptying a string it was right the way you did using a for loop.
There are plenty other ways of emptying the string word by word using for loop:
lcp[i] = '\0';
and it's the right way to make string empty as letter by letter you trying to do using for loop
But if you are not using some loops and simply empty a string then you can do this.
memset(buffer,0,strlen(buffer));
but this will only work for zeroing up to the first NULL character.
If the string is a static array, you can use:
memset(buffer,0,sizeof(buffer));
Your program has a bug: If you supply two identical strings, lcp[i] = 0; never executes which means that your function will return a string which is not NUL-terminated. This will cause undefined behvaior when you use that string in your printf in main.
The fix for this is easy, NUL-terminate the string after the loop:
int i;
for (i = 0; i < min; i++){
if(str1[i] == str2[i])
lcp[i] = str1[i];
else
break;
}
lcp[i] = 0;
As for the answer to the question, an empty string is one which has the NUL-terminator right at the start. We've already handled that as we've NUL-terminated the string outside the loop.
Also, is it necessary to use free(lcp) in the caller function?
In this case, it is not required as the allocated memory will get freed when the program exits, but I'd recommend keeping it because it is good practice.
As the comments say, you can use calloc instead of malloc which fills the allocated memory with zeros so you don't have to worry about NUL-terminating.
In the spirit of code golf. No need to calculate string lengths. Pick any string and iterate through it until the current character either null or differs from the corresponding character in the other string. Store the index, then copy appropriate number of bytes.
char *getlcp(const char *s1, const char *s2) {
int i = 0;
while (s1[i] == s2[i] && s1[i] != '\0') ++i;
char *lcp = calloc((i + 1), sizeof(*lcp));
memcpy(lcp, s1, i);
return lcp;
}
P.S. If you don't care about preserving one of input strings then you can simplify the code even further and just return the index (the position of the last character of the common prefix) from the function, then put '\0' at that index into one of the strings.

Appending a char to a char*

I'm writing a program and I need to append a char to a char*. I have a char** that represents lines of text. I'm trying to take a single char at a time from char**, and add it to a char*.
So basically, I tried strcat(char*, char[i][j]), but strcat rejects char[i][j] since it's not a pointer. I think I need to use sprintf(char*, "%c", char[i][j]), but I'm having trouble understanding how to append with sprintf. I don't want it to overwrite what's already in my char*.
Any tips?
You almost got it!
strncat (char *, & char[i][j], 1);
Calling strncat like that will copy exactly one char from your char** at position [i][j]. Just remember that it will also append the null character after that.
given that you know that buf is defined as
char buf [MAXSIZE];
Let us assume that is has been initialized to an initial string and you want to add mychar to it (a single character)
i = strlen(buf);
if (i < MAXSIZE-1)
{
buf[i] = mychar; // Make the new character the last element of buf
buf[i+1] = '\0' // end the new string with the null character
}
This will append the new character and push the ending null character to ensure that it is a valid string. This is what strcat does when the appended entry is also a string or what strncat does when the count is 1. Note that the new strlen(buf) will now be i+1
Assuming buf is a 0 terminated c-string, you can use snprintf():
#include <stdio.h>
#include <string.h>
int main(void)
{
size_t b_len;
char buf[256];
char ch = '!';
strcpy(buf, "Hello world");
b_len = strlen(buf);
snprintf(buf + b_len, sizeof buf - b_len, "%c", ch);
printf("%s", buf);
char *p = malloc(256); /* check if malloc failed */
strcpy(p, "Hello world");
size_t len = strlen(p);
snprintf(p + len, 256 - len, "%c", ch);
printf("%s", p);
return 0;
}
If buf happens to be pointer (such as an malloced pointer) then you can't use sizeof (it can only be used on an array to get the size).
I have a very hard time understanding your question, instead of posting an example of what you want to achieve you explained something that seems to be based on your way of solving a problem with very little training and/or experience in the c language. So it's hard to write a good answer but definitely I will try to show you a way of doing something similar to what apparently you want to do.
The thing is, I highly doubt that strcat() is appropriate for this or for anything except, concatenating two strings. More than two, require something better than strcat(). And for a single char it's definitely less appropriate.
The following code appends all the characters in the string literal array into a single string, check it out
int
main(int argc, char **argv)
{
char string[100];
char lines[3][14] = {
"First line...",
"Another line.",
"One more line"
};
size_t i;
i = 0;
for (size_t j = 0 ; ((j < sizeof(lines) / sizeof(lines[0])) && (i < sizeof(string) - 1)) ; ++j)
{
for (size_t k = 0 ; ((k < 13) && (i < sizeof(string) - 1)) ; ++k)
string[i++] = lines[j][k];
}
string[i] = '\0';
puts(string);
return 0;
}

Format "%s" expects and agument of type char* etc, I just want to print the alphabet

Why can't I print the alphabet using this code?
void ft_putchar(char c)
{
write(1, &c, 1);
}
int print_alf(char *str)
{
int i;
i = 0;
while (str[i])
{
if (i >= 'A' && i <= 'Z')
ft_putchar(str[i]);
else
ft_putchar('\n');
i++;
}
return (str);
}
int main ()
{
char a[26];
printf("%s", print_alf(a));
return (0);
}
I get this warning
format ' %s ' expects type 'char*' but argument 2 has type 'int'
How do I print the alphabet using a string, and write function?
Your entire print_alf function looks suspicious.
You are returning str which is of type char *. Therefore the return type of print_alf should to be char * instead of int.
Your while (str[i]) loop makes no sense at all since you are passing uninitialized memory to it. So your code will very likely corrupt the memory since the while loop will continue to run until a '\0' is found within the memory which does not need to be the case within the boundaries of the passed memory (a).
You are not adding a zero termination character ('\0') at the end of the string. This will result in printf("%s", print_alf(a)); printing as many characters beginning at the address of a until a '\0' is found within the memory.
Here is a suggestion how to fix all that problems:
char *print_alf(char *str, size_t len)
{
char letter;
if ((str) && (len >= 27)) // is str a valid pointer and length is big enough?
{
for (letter = 'A'; letter <= 'Z'; letter++) // iterate all characters of the alphabet
{
*str = letter;
str++;
}
*str = '\0'; // add zero termination!!!
}
else
{
str = NULL; // indicate an error!
}
return (str);
}
int main()
{
char a[26 + 1]; // ensure '\0' fits into buffer!
printf("%s", print_alf(a, sizeof(a)));
return (0);
}
Make up your mind whether print_alf should return a string which you then print with printf or whether print_alf should be a void function that does the printing, which you should then just call without printf. At the moment, your code tries to be a mixture of both.
The easiest way is to just print the alphabet:
void print_alf(void)
{
int c;
for (c = 'A'; c <= 'Z'; c++) putchar(c);
}
Call this function like so:
print_alf(); // print whole alphabet to terminal
A more complicated variant is to fill a string with the alphabet and then print that string. That's what you tried to achieve, I think. In that case, you must pass a sufficiently big buffer to the function and return it. Note that if you want to use the string functions and features of the standard lib (of which printf("%s", ...) is one) you must null-terminate your string.
char *fill_alf(chat *str)
{
int i;
for (i = 0; i < 26; i++) str[] = 'A' + i;
str[26] = '\0';
return str;
}
It is okay to return the buffer that was passed into the function, but beware of cases where you return local character buffers, which will lead to undefined behaviour.
You can call it as you intended in your original code, but note that you must make your buffer at least 27 characters big to hold the 26 letters and the null terminator:
char a[27];
printf("%s\n", fill_alf(a));
Alternatively, you could do the filling and printing in twp separate steps:
char a[27];
fill_alf(a); // ignore return value, because it's 'a'
printf("%s\n", a); // print filled buffer
If you just want to print the alphabet, the print_alf variant is much simpler and straightforward. If you want to operate further on the alphabet, eg do a shuffle, consider using fill_alf.
Your print_alf(char *str) function actually returns an integer which causes the error (it is defined to return int). When you specify %s to printf it expects characters, not numbers.
You can fix this by changing the return type of your function to char and if everything else works in your code you'll be good to go.

Printing a string due to a new line

Is there any efficient (- in terms of performance) way for printing some arbitrary string, but only until the first new line character in it (excluding the new line character) ?
Example:
char *string = "Hello\nWorld\n";
printf(foo(string + 6));
Output:
World
If you are concerned about performance this might help (untested code):
void MyPrint(const char *str)
{
int len = strlen(str) + 1;
char *temp = alloca(len);
int i;
for (i = 0; i < len; i++)
{
char ch = str[i];
if (ch == '\n')
break;
temp[i] = ch;
}
temp[i] = 0;
puts(temp);
}
strlen is fast, alloca is fast, copying the string up to the first \n is fast, puts is faster than printf but is is most likely far slower than all three operations mentioned before together.
size_t writetodelim(char const *in, int delim)
{
char *end = strchr(in, delim);
if (!end)
return 0;
return fwrite(in, 1, end - in, stdout);
}
This can be generalized somewhat (pass the FILE* to the function), but it's already flexible enough to terminate the output on any chosen delimiter, including '\n'.
Warning: Do not use printf without format specifier to print a variable string (or from a variable pointer). Use puts instead or "%s", string.
C strings are terminated by '\0' (NUL), not by newline. So, the functions print until the NUL terminator.
You can, however, use your own loop with putchar. If that is any performance penalty is to be tested. Normally printf does much the same in the library and might be even slower, as it has to care for more additional constraints, so your own loop might very well be even faster.
for ( char *sp = string + 6 ; *sp != '\0'; sp++ ) {
if ( *sp == '\n' ) break; // newline will not be printed
putchar(*sp);
}
(Move the if-line to the end of the loop if you want newline to be printed.)
An alternative would be to limit the length of the string to print, but that would require finding the next newline before calling printf.
I don't know if it is fast enough, but there is a way to build a string containing the source string up to a new line character only involving one standard function.
char *string = "Hello\nWorld\nI love C"; // Example of your string
static char newstr [256]; // String large enough to contain the result string, fulled with \0s or NULL-terimated
sscanf(string + 6, "%s", newstr); // sscanf will ignore whitespaces
sprintf(newstr); // printing the string
I guess there is no more efficient way than simply looping over your string until you find the first \n in it. As Olaf mentioned it, a string in C ends with a terminating \0 so if you want to use printf to print the string you need to make sure it contains the terminating \0 or yu could use putchar to print the string character by character.
If you want to provide a function creating a string up to the first found new line you could do something like that:
#include <stdio.h>
#include <string.h>
#define MAX 256
void foo(const char* string, char *ret)
{
int len = (strlen(string) < MAX) ? (int) strlen(string) : MAX;
int i = 0;
for (i = 0; i < len - 1; i++)
{
if (string[i] == '\n') break;
ret[i] = string[i];
}
ret[i + 1] = '\0';
}
int main()
{
const char* string = "Hello\nWorld\n";
char ret[MAX];
foo(string, ret);
printf("%s\n", ret);
foo(string+6, ret);
printf("%s\n", ret);
}
This will print
Hello
World
Another fast way (if the new line character is truly unwanted)
Simply:
*strchr(string, '\n') = '\0';

How to know if a char array has a null element in C?

Say if I have :
unsigned char* str = "k0kg"
And 0 is the null element. When I loop through it using a for loop, how do I check if the array has a null?
I tried:
if (str[1]==0):
I also tried:
if (str[1]=="0"):
And they didn't work. :(
The loop:
for (i=0;i<num_bytes;i++){
if (str[i]!=0){
printf("null spotted\n");
}
In C, strings, by definition, are terminated by '\0', the NUL character. So all (valid) strings have a '\0' in them, at the end.
To find the position of the '\0', simply use strlen():
const char * const end = str + strlen(str);
It's odd that you are using "unsigned char" if you are dealing with normal, printable strings. If you mean that you have a memory block with bytes it in and you want to find the first 0x00 byte, then you'll need a pointer to the start of the memory and the size of the memory area, in bytes. Then, you'd use memchr():
// Where strSize is the number of bytes that str points to.
const unsigned char * const end = memchr(str, 0, strSize);
If you are actually looking for the null element then you should do the following condition :
if(str[i]=='\0')
Say if I have : unsigned char* str = "k0kg"
And 0 is the null element. When I loop through it using a for loop, how do I check if the array has a null?
You're terminology is going to confuse any C programmer. You're confusing character representations with values. You're not looking for a null character ("null element", which would be '\0'), you're looking for the character '0'. So...
int len = strlen(str);
for(int i = 0; i < len; ++i) {
if(str[i] == '0')
printf("found it");
}
use strchr
#include <stdio.h>
#include <string.h>
int main(){
char *str = "k0kg";
char *p = strchr(str, '0');
if(p){
printf("find at %d\n", (int)(p - str));//find at 1
}
if(p=strchr(str, 0)){
printf("find at %d\n", (int)(p - str));//find at 4
}
str = "k\0kg";
if(p=strchr(str, 0)){
printf("find at %d\n", (int)(p - str));//find at 1
}
return 0;
}

Resources