I'm trying to make a simple program where parts of other strings are appended to another string. When I run this code, it doesn't output anything. Sorry, my C knowledge is very low. All help appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char stuff[100] = "Y";
char test[] = "hello", test2[] = "shelllo";
strcat(stuff, test[1]);
strcat(stuff, test2[0]);
printf("%s\n", stuff);
return 0;
}
You need to remove array index from your strcat which should look like:
strcat(stuff, test);
strcat(stuff, test2);
Note that test and test2 are strings, but test[1] and test2[0] are just individual characters (e and s) - strcat works with string, not individual characters.
If you want to copy just part of a string (ie skipping first few characters), then use pointer arithmetic
strcat(stuff, test + 1); // skip 1st character of test (ie start copying from `e`)
or,
strcat(stuff, test2 + 3); // skip 3 characters of test2 (ie starting copying from `l`)
You are calling strcat with a char argument instead of a pointer to char, the behavior is undefined.
Here are solutions to copy portions of strings:
using strncat(): it copies no more than a given number of characters to the end of its first argument.
using snprintf() with the %.*s format. The precision field for the %s format specifies the maximum number of characters to copy from the string. It can be specified as a decimal number or as a * in which case the precision is passed as an int argument before the string argument.
Here is an example:
#include <stdio.h>
#include <string.h>
int main(void) {
char stuff[100];
char test[] = "Hello";
char test2[] = "The world is flat";
/* using strncat */
strcpy(stuff, test);
strncat(stuff, test2 + 3, 6);
printf("%s\n", stuff);
/* safer version using snprintf */
snprintf(stuff, sizeof stuff, "Hello %.*s\n", 5, test2 + 4);
printf("%s\n", stuff);
return 0;
}
Related
I'm trying to use sprintf() to put a string "inside itself", so I can change it to have an integer prefix. I was testing this on a character array of length 12 with "Hello World" inside it already.
The basic premise is that I want a prefix that denotes the amount of words within a string. So I copy 11 characters into a character array of length 12.
Then I try to put the integer followed by the string itself by using "%i%s" in the function. To get past the integer (I don't just use myStr as the argument for %s), I make sure to use myStr + snprintf(NULL, 0, "%i", wordCount), which should be myStr + characters taken up by the integer.
The problem is that I'm having is that it eats the 'H' when I do this and prints "2ello World" instead of having the '2' right beside the "Hello World"
So far I've tried different options for getting "past the integer" in the string when I try to copy it inside itself, but nothing really seems to be the right case, as it either comes out as an empty string or just the integer prefix itself '222222222222' copied throughout the entire array.
int main() {
char myStr[12];
strcpy(myStr, "Hello World");//11 Characters in length
int wordCount = 2;
//Put the integer wordCount followed by the string myStr (past whatever amount of characters the integer would take up) inside of myStr
sprintf(myStr, "%i%s", wordCount, myStr + snprintf(NULL, 0, "%i", wordCount));
printf("\nChanged myStr '%s'\n", myStr);//Prints '2ello World'
return 0;
}
First, to insert a one-digit prefix into a string “Hello World”, you need a buffer of 13 characters—one for the prefix, eleven for the characters in “Hello World”, and one for the terminating null character.
Second, you should not pass a buffer to snprintf as both the output buffer and an input string. Its behavior is not defined by the C standard when objects passed to it overlap.
Below is a program that shows you how to insert a prefix by moving the string with memmove. This is largely tutorial, as it is not generally a good way to manipulate strings. For short strings, where space is not an issue, most programmers would simply print the desired string into a temporary buffer, avoiding overlap issues.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Insert a decimal numeral for Prefix into the beginning of String.
Length specifies the total number of bytes available at String.
*/
static void InsertPrefix(char *String, size_t Length, int Prefix)
{
// Find out how many characters the numeral needs.
int CharactersNeeded = snprintf(NULL, 0, "%i", Prefix);
// Find the current string length.
size_t Current = strlen(String);
/* Test whether there is enough space for the prefix, the current string,
and the terminating null character.
*/
if (Length < CharactersNeeded + Current + 1)
{
fprintf(stderr,
"Error, not enough space in string to insert prefix.\n");
exit(EXIT_FAILURE);
}
// Move the string to make room for the prefix.
memmove(String + CharactersNeeded, String, Current + 1);
/* Remember the first character, because snprintf will overwrite it with a
null character.
*/
char Temporary = String[0];
// Write the prefix, including a terminating null character.
snprintf(String, CharactersNeeded + 1, "%i", Prefix);
// Restore the first character of the original string.
String[CharactersNeeded] = Temporary;
}
int main(void)
{
char MyString[13] = "Hello World";
InsertPrefix(MyString, sizeof MyString, 2);
printf("Result = \"%s\".\n", MyString);
}
The best way to deal with this is to create another buffer to output to, and then if you really need to copy back to the source string then copy it back once the new copy is created.
There are other ways to "optimise" this if you really needed to, like putting your source string into the middle of the buffer so you can append and change the string pointer for the source (not recommended, unless you are running on an embedded target with limited RAM and the buffer is huge). Remember code is for people to read so best to keep it clean and easy to read.
#define MAX_BUFFER_SIZE 128
int main() {
char srcString[MAX_BUFFER_SIZE];
char destString[MAX_BUFFER_SIZE];
strncpy(srcString, "Hello World", MAX_BUFFER_SIZE);
int wordCount = 2;
snprintf(destString, MAX_BUFFER_SIZE, "%i%s", wordCount, srcString);
printf("Changed string '%s'\n", destString);
// Or if you really want the string put back into srcString then:
strncpy(srcString, destString, MAX_BUFFER_SIZE);
printf("Changed string in source '%s'\n", srcString);
return 0;
}
Notes:
To be safer protecting overflows in memory you should use strncpy and snprintf.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I've been trying to learn C programming by reading a textbook, but am confused about how strings and substrings work.
I have an idea of what strings and substrings are from java, but can't figure out the syntax in C.
Here's a question from the book that I thought might be easy, but I can't get it.
Write and test a function hydroxide that returns a 1 for true if its string argument ends in the substring OH.
It recommends testing the function with KOH and NaCl.
Also, how would I remove and add letters at the end of the string?
Like, if for some reason I wanted to change NaCl to NaOH?
Any help and explanations would be really appreciated.
ETA:
I guess what I'm most confused on is how to make the program look at the last two letters in the string and compared them to OH.
I'm also not sure how to pass strings to functions.
String is a sequence of characters that ends with special null-terminated character '\0'. If there is no \0, functions that work with string won't stop until the \0 symbol is found. This character may happen in any place after the end of pseudo string (I mean a string without \0) and only then stop.
The following example shows the necessity of this null-terminated character:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char string[] = "Hello!";
printf("original string:\n%s\n\n", string);
memset(string, '-', 5);
printf("memset doesn't affect the last two symbols: '!' and '\\0':\n%s", string);
memset(string, '-', 6);
printf("\n\nmemset doesn't affect the last symbol: '\\0':\n%s\n\n", string);
memset(string, '-', 7);
printf("memset affects all symbols including null-terminated one:\n%s", string);
return 0;
}
/* OUTPUT:
original string:
Hello!
memset doesn't affect the last two characters: '!' and '\0':
-----!
memset doesn't affect the last character: '\0':
------
memset affects all characters including null-terminated one:
-------#↓#
*/
Substring is a char sequence that is in a string. It may be less or equal to the string.
Suppose, "NaOH" is a string. Then substring may be: "N", "a", "O", "H", "Na", "aO", "OH", "NaO", "aOH", "NaOH". To find whether substring is in the string or not you can use strstr function. It's prototype is char * strstr ( char * str1, const char * str2 );.
This code shows this function's results:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *ptrCh = NULL;
ptrCh = strstr("hello", "h");
printf("ptrCh: %p\n", ptrCh);
printf("%s\n\n", ptrCh);
ptrCh = strstr("hello", "z");
printf("ptrCh: %p\n", ptrCh);
printf("%s\n\n", ptrCh);
return 0;
}
/* OUTPUT:
ptrCh: 00403024
hello
ptrCh: 00000000
(null)
*/
As for the first printf, it prints characters beginning from the position of 'h' and when it reaches null-terminated character, which is next after 'o', it stops, exactly as in previous program.
To make your program more interactive, you can declare array and then a pointer to it. Array size must be enough to store the longest formula. Suppose, 100 will be enough:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buf[100] = {0};
char *ptr = &buf[0];
scanf("%s", ptr);
// printf() gets a pointer as argument
printf("%s\n", ptr);
// printf() gets also a pointer as argument.
// When you pass arrays name without index to a function,
// you pass a pointer to array's first element.
printf("%s", buf);
return 0;
}
And as for rewriting letters in the end of the string. Here is a small program that does it. Pay attention at comments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buf[100] = {0};
char formula[100] = {0};
char compound[100] = {0};
char *ptr = &buf[0];
char *pFormula = &formula[0];
char *pCompound = &compound[0];
printf("Enter formula: ");
scanf("%s", pFormula);
printf("Enter chemical compound: ");
scanf("%s", pCompound);
// Copying the first chemical elements without the last
// several that will be replaced by another elements.
strncpy(ptr, pFormula, strlen(pFormula) - strlen(pCompound));
// Adding new compound to the first elements.
// Function also adds a null-terminated character to the end.
strncat(ptr, pCompound, strlen(pCompound));
printf("The new chemical compound is: ");
printf("%s", ptr);
return 0;
}
/* OUTPUT:
Enter formula: NaOH
Enter chemical compound: Cl
The new chemical compound is: NaCl
*/
In C, we use null-terminated strings. That is the "invisible", 0 value. Not ASCII "0", but the zero value, like 8-bit 0x00. You can represent it in literal text with '\0' or "\0" or unquoted 0, however, in a literal string it is redundant because most functions like strcmp() or strstr() or strcat() all expect and work with null terminated strings. Null char is the stops sign for the C standard string functions.
One easy way to implement this with C library calls is to test for existence of the substring and then test that substring's length, which verify it is at end of string.
Assume buf is some big string buffer, char buf[1024] and char *temp is a temporary variable.
temp = strstr(buf, "OH") returns the pointer to "OH" if exists in buf at any offset.
strlen(temp) Get length of temp, if at end of string, it will be 2 (doesn't include null terminator), so if the original string is "OHIO" or "SOHO" it wont match because it'll be 4 and 3 respectively.
The above is the core of the code, not the full robust implementation. You need to check for valid return values, etc.
char buf[1024];
char *temp;
strcpy(buf, "NaOH");
if((temp = strstr(buf, "OH")) != 0)
{
// At this point we know temp points to something that starts with "OH"
// Now see if it is at the end of the string
if(strlen(temp) == 2)
return true; // For C99 include stdbool.h
return false;
}
You could get obscure, and check for the null terminator directly, will be a smidge quicker. This code is safe as long as it is inside the if() for strstr(), otherwise never do this if you don't know a string is a least N characters long.
if(temp[2] == '\0')
return true; // For C99 include stdbool.h
As far as appending to a string, read the docs on strcat. Keep in mind with strcat, you must have enough space already in the buffer you are appending into. It isn't like C++ std::string or Java/C# string where those will dynamically resize as needed. In C, you get to do all of that yourself.
I am very new in C, I have little idea about sprintf but I can't fulfill my requirement.
I have a char * variable which contains string like below :
date=2013-12-09 time=07:31:10 d_id=device1 logid=01 user=user1 lip=1.1.1.1 mac=00:11:22:33:44:55 cip=2.2.2.2 dip=3.3.3.3 proto=AA sport=22 dport=11 in_1=eth1 out_1=
I want an output as
2013-12-09#07:31:10#device1#01#user1#1.1.1.1#00:11:22:33:44:55#2.2.2.2#3.3.3.3#AA#22#11#eth1##
if some value is null after = it should print ## in sequence.
I am not going to give you exact code but I will give you some links that will help you.
strchr :: You can use this find the position of '=' in the string.
Now, copy the string after the position of '=' till you find a 'space'.
Whenever you will find a 'space', write a '#' in the buffer.
Keep doing this, till you encounter a '\0'. Write '##' to buffer when you have encountered '\0'
Append that with a '\0'.
Ex:: C function strchr - How to calculate the position of the character?
example by use strtok, strchr, sprintf
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
const char *data = "date=2013-12-09 time=07:31:10 d_id=device1 logid=01 user=user1 lip=1.1.1.1 mac=00:11:22:33:44:55 cip=2.2.2.2 dip=3.3.3.3 proto=AA sport=22 dport=11 in_1=eth1 out_1=";
char *work = strdup(data);//make copy for work
char *output = strdup(data);//allocate for output
char *assignment; //tokenize to aaa=vvv
size_t o_count = 0;//output number of character count
for(assignment=strtok(work, " "); assignment ;assignment=strtok(NULL, " ")){
o_count += sprintf(output + o_count, "%s#", strchr(assignment, '=')+1);
}
printf("%s", output);
free(work);
free(output);
return 0;
}
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.
I wrote a program in ANSI C to remove the double quote in front and in the end of a string, so "Hello, world" would become Hello, world:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* removeQuotes(char str[]) {
int i = 1;
int len = strlen(str) - 2;
char * tmp = (char*) malloc (sizeof(char) * len);
for (;i<=len;++i ) {
tmp[i-1] = str[i];
}
return tmp;
}
int main(void) {
char str[] = "Hello, world";
char * abc = removeQuotes(str);
printf("Inside the quotes is: %s length: %d\n"
"Original is: %s length: %d", abc, strlen(abc), str, strlen(str));
return 0;
}
In IDEOne (http://ideone.com/Iybuk) I get the correct answer. But GCC gives me something weird:
U→┬↓ length: 22es is: ello, worlESSOR_↑
Original is: Hello, world length: 12
It happens only when the string contains a space. It works fine with "Helloworld" or something like that.
Any robust method to get it work correctly?
You have not allocated enough space for the null terminator.
You don't add the null terminator to the end of your result.
Your source string doesn't actually contain quotes.
In C strings are terminated by a null character, that means '\0'.
You didn't terminate string in removeQuotes(), this is the correct version:
char* removeQuotes(char str[]) {
int i = 1;
int len = strlen(str) - 2;
char * tmp = (char*) malloc (sizeof(char) * (len + 1));
for (;i<=len;++i ) {
tmp[i-1] = str[i];
}
tmp[len] = '\0';
return tmp;
}
Also, your string actually didn't contain quotes and you do not check if the string you pass to removeQuotes contain any quotes.
In your removeQuotes function you underallocate memory for the resulting string and write an extra character past the buffer.
The string "Hello world" doesn't actually contain any quotes. You'd have to declare it as "\"Hello world\"" to have the string you had in mind. In any case, the string resulting from your quote removal has the same number of characters as the input one. You lose the first character, because you never copy it, and the last one gets written past the buffer (and it would be written there, clobbering memory, even if it were a quote mark.
Why do you need to do this anyway? Do you believe that C strings are created with quote characters in the first and last positions of the character array?
Keep a '\0' in temp string. otherwise it will not know that it is a string.