How to get the start of an email address - c

I have two strings, one with an email address, and the other is empty.
If the email adress is e.g. "abc123#gmail.com", I need to pass the start of the email address, just before the # into the second string. For example:
first string: "abc123#gmail.com"
second string: "abc123"
I've written a loop, but it doesn't work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char email[256] = "abc123#gmail.com";
char temp[256];
int i = 0;
while (email[i] != '#')
{
temp = strcat(temp, email[i]);
i++;
}
printf ("%s\n", temp);
system ("PAUSE");
return 0;
}
Basically, I took every time one char from the email address, and added it into the new string. For example if the new string has a on it, now I'll put b with it too using strcat....

Pointers. Firstly, strcat() returns a char pointer, which C can't cast as a char array for some reason (which I hear all C programmers must know). Secondly, the second argument to strcat() is supposed to be a char pointer, not a char.
Replacing temp = strcat(temp, email[i]); with temp[i] = email[i]; should do the trick.
Also, after the loop ends, terminate the string with a null character.
temp[i] = '\0';
(After the loop ends, i is equal to the length of your extracted string, so temp[i] is where the terminal should go.)

There are better ways to solve this problem (e.g. by finding the index of the # (by strcspn or otherwise) and doing a memcpy), but your method is very close to working, so we can just make a few small adjustments.
As others have identified, the problem is with this line:
temp = strcat(temp, email[i]);
Presumably, you are attempting to copy the character at the ith position of email into the corresponding position of temp. However, strcat is not the correct way to do so: strcat copies data from one char* to another char*, that is, it copies strings. You just want to copy a single character, which is exactly what = does.
Looking at it from a higher level (so that I don't just tell you the answer), you want to set the appropriate character of temp to the appropriate character of email (you will need to use i to index both email and temp).
Also, remember that strings in C have to be terminated by '\0', so you have to set the next character of temp to '\0' after you have finished copying the string. (On this line of thought, you should consider what happens if your email string doesn't have an # in it, your while loop will keep going past the end of the string email: remember that you can tell if you are at the end of a string by character == '\0' or just using character as a condition.)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char email[256] = "abc123#gmail.com";
char temp[256];
size_t i = 0;
#if 0
for (i=0; email[i] && email[i] != '#'; i++) {;}
/* at the end of the loop email[i] is either the first '#',
** or that of the terminating '\0' (aka as strlen() )
*/
#else
i = strcspn(email, "#" );
/* the return value for strcspn() is either the index of the first '#'
* or of the terminating '\0'
*/
#endif
memcpy (temp, email, i);
temp[i] = 0;
printf ("%s\n", temp);
system ("PAUSE");
return 0;
}
UPDATE: a totally different approach would be to do the copying inside the loop (I guess this was the OP's intention):
for (i=0; temp[i] = (email[i] == '#' ? '\0' : email[i]) ; i++) {;}

You may want to try using strtok()

Related

Add one character from a string to the end of another string (strcat)

for (unsigned int i = 0; i < strlen(s); i++) {
if (s[i] != ' ')
strcat(p, s[i]);
I want to add the current character of the s string at the end of the p string provided it is not a space. How do I do that using strcat? The code above gives the following error "invalid conversion from 'char' to 'const char*'".
I want to use strcat because this way I don't have to store an index for p string in order to know where to place the current character. I hope this makes sense.
Also, I need to do this using array of chars, not c-strings or whatever those are called.
A more sensible algorithm would avoid using strcat() or strncat() altogether:
int j = strlen(p);
for (int i = 0; s[i] != '\0'; i++)
{
if (s[i] != ' ')
p[j++] = s[i];
}
p[j] = '\0';
This avoids quadratic behaviour which using strlen() and strcat() (or strncat()) necessarily involves. It does mean you need to keep a track of where to place characters in p, but the work involved in doing that is trivial. Generally speaking, the quadratic behaviour won't be a problem on strings of 10 characters or so, but if the strings reach 1000 bytes or more, then quadratic behaviour becomes a problem (it takes 1,000,000 operations instead of 1,000 operations — that can become noticeable).
First, you need addresses (the array itself is an address to the first element) to pass to the strcat, not a char. That is why you need to use the & operator before s[i].
You have a working example here
#include <stdio.h>
#include <string.h>
int main()
{
char s[50]= "Hello World";
char p[50]= "Hello World";
for(unsigned int i=0;i<strlen(s);i++){
if(s[i]!=' ')
strncat(p,&s[i],1);
}
puts(p);
return 0;
}

Displaying lines with given number of characters

I have written such a program which suppose to returns lines which are containing at least 11 characters and 4 digits. I messed up something with types of variables I guess but I cant figure out how should I fix it.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
char line[200];
char *temp[200];
int i = 0, k=0;
printf("Enter a string: \n");
while(fgets(line, sizeof(line),stdin))
{
int numberAlpha = 0;
int numberDigit = 0;
int i;
for(i=0; i<strlen(line); i++){
if(isalpha(line[i])) numberAlpha++;
else if(isdigit(line[i])) numberDigit++;
}
if(numberAlpha+numberDigit>10 && numberDigit>3){
temp[i]=line;
i++;
}
}
while(temp[k]!='\0'){
printf("%s", temp[k]);
k++;
}
return 0;
}
You're reusing the same buffer each time, and you're storing a pointer to that buffer in your temp array. What you're going to end up with is a bunch of the same pointer in that array, with that pointer pointing at the last line in the file.
What you can do instead is to rewrite your temp[i]=line statement to the following:
temp[i] = malloc(sizeof(line))
memcpy(temp[i], line, sizeof(line))
In so doing, you'll be creating a new array with the contents of the matching line, which won't get overwritten when you come around and read the next line out of the file.
Note that, because you're allocating that on the heap, at the end of your function you'll want to free it:
while (temp[k] != '\0') {
printf(...);
free(temp[k]);
k++
}
As said before , one issue is with copying of
temp[i]=line;
This can be solved by doing a new heap allocation and doing memcopy to temp.
The other issue that i could see is - with the value of variable i. Then temp array will always be assigned to strlen(line) index. You might be thinking of storing in the temp array from 0. Which is not happening.
This can be solved by-
int start_index=0;
while(...){
if(numberAlpha+numberDigit>10 && numberDigit>3){
temp[start_index]=line;
start_index++;
}
}
The problem is you are assigning the same address here:
temp[i]=line;
and line is used in the loop to read as well. That means it's overwritten in every iteration.
Instead, you can use strdup() (POSIX function):
temp[i] = strdup(line);
to copy the lines you are interested in. If strdup() not available you can use malloc() + strcpy() to do the same. Plus, free() them later.
In addition, be aware that:
fgets() will read in the newline character if there's room in the buffer which may not be what you want. So, you need to trim it out. You can do it with:
line[strcspn(line, "\n")] = 0; /* trim the trailing newline, if any */
The arguments to isalpha() and isdigit() should be cast to unsigned char to avoid potential undefined behaviour i.e. these two lines:
if(isalpha(line[i])) numberAlpha++;
else if(isdigit(line[i])) numberDigit++;
should be
if(isalpha((unsigned char)line[i])) numberAlpha++;
else if((unsigned char)isdigit(line[i])) numberDigit++;

How to use getchar() function from a stored string array?

I wrote a simple C program in Linux that reads a single character from a string. I get some error regarding string functions. This is my code:
#include <stdio.h>
#include <string.h>
void main () {
char arr[10], vv[10];
int i = 0, len;
printf("enter the staement\n");
scanf("%s", arr);
len = strlen(arr);
printf("String laength=%d\n", len);
while ((vv[i] = getchar(arr)) != '\n') {
printf("%d charcter\n");
i++;
}
}
I don't want to use getchar() directly on the input text like this:
arr[i] = getchar();
I want to use getchar() from a stored string like this:
getchar(string array);
But unfortunately I get an error. Can I use the getchar() function directly from a stored string array?
Read about getchar. The link clearly says that getchar is a function that gets a character (an unsigned char) from stdin. Also, it takes no arguments. This would mean that you cannot copy each character of an array to another array using getchar. Just copy it directly using
while( (vv[i] = arr[i]) != '\n')
But I don't think this loop will end as scanf does not include the newline character when scanning a string(%s). So,you got two options:
Use fgets to get input.
Use the following
while( (vv[i] = arr[i]) != '\0')
When you have string in C, it is actually an array of chars which is terminated by '\0'. You do not need any method to get chars from it. Simply get the char as if you were accessing an array.
while((vv[i] = arr[i])!='\n')
As you have you arr[10] it will cause issues when your input is larger than 10 characters including the '\0'. So it is be better to declare it with enough space!
vv is a single char. You may not write vv[i].
Also, are you sure you want \n and not \0 [null]? scanf() won't give you a string with \n in it.
EDIT:
It is still unclear what you want to achieve, but if you want to check the presence of valid characters in the arr or vv, you can
take the base address of the arr or vv into a char *p.
check if (*p++) and do something.
EDIT:
You may try out something like
char * ip = NULL;
char * op = NULL;
int i = 10; //same as array size.
ip = arr;
op = vv;
while( (*op++ = *ip++) && i--)
{
//do something
};

Initializing end of the string in C

I am learning C now and I'm at the point where I don't really get what is the difference of initializing the end of the string with NULL '\0' character. Below is the example from the book:
#include <stdio.h>
#include <string.h>
int main(){
int i;
char str1[] = "String to copy";
char str2[20];
for(i = 0; str1[i]; i++)
str2[i] = str1[i];
str2[i] = '\0'; //<====WHY ADDING THIS LINE??
printf("String str2 %s\n\n", str2);
return 0;
}
So, why do I have to add NULL character? Because it works without that line as well. Also, is there a difference if I use:
for (i = 0; str1[i]; i++){
str2[i] = str1[i];
}
Thanks for your time.
The line you're referring to is added in general use for safety. When you copy values to a string you always want to be sure that it's null terminated, otherwise when reading the string it will continue past the point where you want the end of that string to be (because it doesn't know where to stop due to lack of the null terminator).
There is no difference with the alternate code you posted since you are separating only the line below the for statement to be in the loop, which happens by default anyway if you don't use the curly braces {}
In C, the end of the string is detected by the null character. Consider the string 'abcd'. If the variable in the actual binary have the next variable immediately after the 'd' character, C will think that the next characters in the platform are part of that string and you will continue. This is called buffer overrun.
Your initial statement allowing 20 bytes for str2 will usually fill it with 20 zeroes, However, this is not required and may not occur. Additionally, let us say you move a 15 character string into str2. Since it starts with 20 zeroes, this will work. However, say that you then copy a 10 character string into str2. The remaining 5 characters will be unchanged and you will then have a 15 character string consisting of the new 10 characters, followed by the five characters previously copied in.
In the code above the for loop says move the character in str1 to str2 and point to the next character. If the character now pointed to in str1 is not 0, loop back and do again. Otherwise drop out of the loop. Now add the null character to the end of the str2. If you left that out, the null character at the end of str1 would not be copied to str2, and you would have no null character at the end of str2.
This can be expressed as
i = 0;
label:
if (str1[i] == 0) goto end;
str2[i] = str1[i];
i = i + 1;
goto label;
end: /* This is the end of the loop*/
Note that the '\0' character has not yet been moved into str2.
Since C requires brackets to show the range of the for, only the first line after the for is part of the loop. If i had local scope and is lost after the loop, you would not be able to just wait to fall out of the loop and make it 0. You would no longer have a valid i pointer to tell you where in str2 you need to add the 0.
An example is C++ or some compilers in C which would allow (syntactically)
for (int i = 0; str1[i]; i++)
{
str2[i] = str1[i];
}
str2[i] = 0;
This would fail because i would be reset to whatever it happened to be before it entered the loop (probably 0) as it falls out of the loop. If it had not been defined before the loop, you would get an undefined variable compiler error.
I see that you fixed the indentation, but had the original indentation stayed there, the following comment would apply.
C does not work solely by indentation (as Python does, for example). If it did, the logic would be as follows and it would fail because str2 would be overwritten as all 0.
for (int i = 0; str1[i]; i++)
{
str2[i] = str1[i];
str2[i] = 0;
}
You should only add a \0 (also called the null byte) in the end of the string. Do as follows:
...
for(i = 0; str1[i]; i++) {
str2[i] = str1[i];
}
str2[i] = '\0'; //<====WHY ADDING THIS LINE??
...
(note that I simply added braces to make the code more readable, it was confusing before)
For me, that is clearer. What you were doing before is basically take advantage of the fact that the integer i that you declared is still available after you ran the loop to add a \0 in the end of str2.
The way strings work in C is that they are basically a pointer to the location of the first character and string functions (such as the ones you can find in string.h) will read every single char until they find a \0 (null byte). It is simply a convention for marking the end of the string.
Some further reading: http://www.cs.nyu.edu/courses/spring05/V22.0201-001/c_tutorial/classes/String.html
'\0' is used for denoting end of string. It is not for the compiler, it is for the libraries and possibly your code. C does not support arrays properly. You can have local arrays, but there is no way to pass them about. If you try you just pass the start address (address of first element). So you can ever have the last element be special e.g. '\0' or always pass the size, being careful not to mess up.
For example:
If your string is like this:
char str[]="Hello \0 World";
will you tell me what would display if you print str ?
Output is:
Hello
This will be the case in character arrays, Hence to be in safer side, it is good to add '\0'at the end of string.
If you didnt add '\0', some garbage values might get printed out, and it will keep on printing till it reached '\0'
In C, char[] do not know the length of the string. It is therefore important character '\0' (ASCII 0) to indicate the end of the string. Your "For" command will not copy '\0', so output is a string > str2 (until found '\ 0' last stop)
Try:
#include <stdio.h>
#include <string.h>
int main(){
int i;
char str[5] = "1234";
str[4] = '5';
printf("String %s\n\n", str);
return 0;
}

Need help finding bug, if string input is composed all of same character one output character is corrupt

reverser() reverses a cstring (not in place). 99% of the time it works but some input corrupts it for example it appears if aStr2[] is assigned a string made up of the same character it will have an error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* reverser(const char *str);
int main()
{
char aStr[] = "aaa";
char aStr2[] = "cccccc";
printf("%s %s", aStr, aStr2);
char* tmp = reverser(aStr2);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr2);
return 0;
}
char* reverser(const char *str)
{
char* revStr = (char*)malloc(strlen(str));
int i;
for(i = strlen(str)-1; i >= 0; i--)
{
revStr[strlen(str)-1-i] = str[i];
}
return revStr;
}
Gives
aaa cccccc
cccccc9 cccccc
Process returned 0 (0x0) execution time : 0.068 s
Press any key to continue
Notice the 9 that shouldn't be there.
Change this malloc to strlen(str) + 1 , plus 1 for '\0'
char* revStr = (char*)malloc(strlen(str) + 1);
and after the for loop
revStr[strlen(str)+1] = '\0';
Your problem is that you don't put the string terminator in your reversed string. All strings in C are actually one extra character that isn't reported by strlen, and that is the character '\0' (or plain and simple, a zero). This tells all C functions when the string ends.
Therefore you need to allocate space for this extra terminator character in your malloc call, and add it after the last character in the string.
There are also a couple of other problems with your code, the first is that you should not cast the return of malloc (or any other function returning void *). Another that you have a memory leak in that you do not free the memory you allocate. This last point doesn't matter in a small program like the one you have here, but will be an issue in larger and longer running programs.
You haven't null-terminated your reversed string. You need to set the final index of revStr[] to 0.

Resources