How to append string using snprint() function - c

#include<stdio.h>
main()
{
char str[50] = "Wel %s";
char dst[50];
snprintf(dst,50,str,"Come");
//Now i want to append "*" to dst string ie "Wel Come*" using snprintf()
printf("str = %s\n",str);
printf("dst = %s\n",dst);
}
please suggest is it possible using snprintf()
Thanks
Surya

The obvious solution:
snprintf(dst,50,"%s*",dst);
is inefficient, because it makes an unnecessary copy of dst (into itself).
invokes undefined behavior as R. pointed out, because the arguments may not overlap (from man snprintf(3) on MacOSX):
"[...]or those routines that write to
a user-provided character string, that
string and the format strings should
not overlap, as the behavior is
undefined."
Posix says:
http://www.opengroup.org/onlinepubs/000095399/functions/printf.html
"If copying takes place between
objects that overlap as a result of a
call to sprintf() or snprintf(), the
results are undefined."
snprintf returns the number of characters it has written, so you can do this instead:
int k=snprintf(dst,50,str,"Come");
// make sure that we do not pass potential disastrous values to snprintf, because
// the size argument is unsigned (size_t, 50-52 is a large positive number!)
// and we want 50-k to be in the range 0-50
// k<0 means output error and k>50 means "output truncated". There is no point in
// appending anything in these cases anyway.
if (k<0 || k>50)
{
fprintf(stderr,"output error or buffer too small");
}
else k=snprintf(dst+k,50-k,"*");
// check k for truncation here.
And then there's always strcat...And just in case, you overlooked it. You can have the * attached right in the first place:
main()
{
char str[50] = "Wel %s*"; //<--!!!
[...]

This should work:
#include<stdio.h>
int main()
{
char str[50] = "Wel %s";
char dst[50];
int len;
snprintf(dst,50,str,"Come");
//get size of current string
len = strlen(dst);
//add character to the end
snprintf(dst + len, sizeof(dst) - len, "*");
printf("str = %s\n",str);
printf("dst = %s\n",dst);
return 0;
}

you can use the %s format for this:
snprintf(dst, 50, "%s*", dst);
EDIT: This seems to have some undefined behaviors. The best thing would be to ask if it is really necessary to use snprintf instead of strncat.

All the information is already available to you:
snprintf(dst + 8, sizeof(dst) - 8, "%s", "*");
You'd be better off doing:
strncat(dst, "*", sizeof(dst) - strlen(dst) - 1);

Related

C - Using sprintf() to put a prefix inside of a string

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.

My function goes over the length of string

I am trying to make function that compares all the letters from alphabet to string I insert, and prints letters I didn't use. But when I print those letters it goes over and gives me random symbols at end. Here is link to function, how I call the function and result: http://imgur.com/WJRZvqD,U6Z861j,PXCQa4V#0
Here is code: (http://pastebin.com/fCyzFVAF)
void getAvailableLetters(char lettersGuessed[], char availableLetters[])
{
char alphabet[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int LG,LG2,LA=0;
for (LG=0;LG<=strlen(alphabet)-1;LG++)
{
for(LG2=0;LG2<=strlen(lettersGuessed)-1;LG2++)
{
if (alphabet[LG]==lettersGuessed[LG2])
{
break;
}
else if(alphabet[LG]!=lettersGuessed[LG2] &&LG2==strlen(lettersGuessed)-1)
{
availableLetters[LA]=alphabet[LG];
LA++;
}
}
}
}
Here is program to call the function:
#include <stdio.h>
#include <string.h>
#include "hangman.c"
int main()
{
int i = 0;
char result[30];
char text[30];
scanf("%s", text);
while(i != strlen(text))
{
i++;
}
getAvailableLetters(text, result);
printf("%s\n", result);
printf ("%d", i);
printf ("\n");
}
Here is result when I typed in abcd: efghijklmnopqrstuvwxyzUw▒ˉ
If you want to print result as a string, you need to include a terminating null at the end of it (that's how printf knows when to stop).
for %s printf stops printing when it reaches a null character '\0', because %s expects the string to be null terminated, but result not null terminated and that's why you get random symbols at the end
just add availableLetters[LA] = '\0' at the last line in the function getAvailableLetters
http://pastebin.com/fCyzFVAF
Make sure your string is NULL-terminated (e.g. has a '\0' character at the end). And that also implies ensuring the buffer that holds the string is large enough to contain the null terminator.
Sometimes one thinks they've got a null terminated string but the string has overflowed the boundary in memory and truncated away the null-terminator. That's a reason you always want to use the form of functions (not applicable in this case) that read data, like, for example, sprintf() which should be calling snprintf() instead, and any other functions that can write into a buffer to be the form that let's you explicitly limit the length, so you don't get seriously hacked with a virus or exploit.
char alphabet[]={'a','b','c', ... ,'x','y','z'}; is not a string. It is simply an "array 26 of char".
In C, "A string is a contiguous sequence of characters terminated by and including the first null character. ...". C11 §7.1.1 1
strlen(alphabet) expects a string. Since code did not provide a string, the result is undefined.
To fix, insure alphabet is a string.
char alphabet[]={'a','b','c', ... ,'x','y','z', 0};
// or
char alphabet[]={"abc...xyz"}; // compiler appends a \0
Now alphabet is "array 27 of char" and also a string.
2nd issue: for(LG2=0;LG2<=strlen(lettersGuessed)-1;LG2++) has 2 problems.
1) Each time through the loop, code recalculates the length of the string. Better to calculate the string length once since the string length does not change within the loop.
size_t len = strlen(lettersGuessed);
for (LG2 = 0; LG2 <= len - 1; LG2++)
2) strlen() returns the type size_t. This is some unsigned integer type. Should lettersGuessed have a length of 0 (it might have been ""), the string length - 1 is not -1, but some very large number as unsigned arithmetic "wraps around" and the loop may never stop. A simple solution follows. This solution would only fail is the length of the string exceeded INT_MAX.
int len = (int) strlen(lettersGuessed);
for (LG2 = 0; LG2 <= len - 1; LG2++)
A solution without this limitation would use size_t throughout.
size_t LG2;
size_t len = strlen(lettersGuessed);
for (LG2 = 0; LG2 < len; LG2++)

strcat() for formatted strings

I'm building a string piece by piece in my program and am currently using a mix of strcat() when I'm adding a simple string onto the end, but when im adding a formatted string I'm using sprintf() e.g.:
int one = 1;
sprintf(instruction + strlen(instruction), " number %d", one);
is it possible to concatenate formatted string using strcat() or what is the preferred method for this?
Your solution will work. Calling strlen is a bit awkward (particularly if the string gets quite long). sprintf() will return the length you have used [strcat won't], so one thing you can do is something like this:
char str[MAX_SIZE];
char *target = str;
target += sprintf(target, "%s", str_value);
target += sprintf(target, "somestuff %d", number);
if (something)
{
target += sprintf(target, "%s", str_value2);
}
else
{
target += sprintf(target, "%08x", num2);
}
I'm not sure strcat is much more efficient than sprintf() is when used in this way.
Edit: should write smaller examples...
no it's not possible but you could use sprintf() on those simple strings and avoid calling strlen() every time:
len = 0;
len += sprintf(buf+len, "%s", str);
len += sprintf(buf+len, " number %d", one);
To answer the direct question, sure, it's possible to use strcat to append formatted strings. You just have to build the formatted string first, and then you can use strcat to append it:
#include <stdio.h>
#include <string.h>
int main(void) {
char s[100];
char s1[20];
char s2[30];
int n = 42;
double x = 22.0/7.0;
strcpy(s, "n = ");
sprintf(s1, "%d", n);
strcat(s, s1);
strcat(s, ", x = ");
sprintf(s2, "%.6f", x);
strcat(s, s2);
puts(s);
return 0;
}
Output:
n = 42, x = 3.142857
But this is not a particularly good approach.
sprintf works just as well writing to the end of an existing string. See Mats's answer and mux's answer for examples. The individual arrays used to hold individual fields are not necessary, at least not in this case.
And since this code doesn't keep track of the end of the string, the performance is likely to be poor. strcat(s1, s2) first has to scan s1 to find the terminating '\0', and then copy the contents of s2 into it. The other answers avoid this by advancing an index or a pointer to keep track of the end of the string without having to recompute it.
Also, the code makes no effort to avoid buffer overruns. strncat() can do this, but it just truncates the string; it doesn't tell you that it was truncated. snprintf() is a good choice; it returns the number of characters that it would have written if enough space were available. If this exceeds the size you specify, then the string was truncated.
/* other declarations as above */
size_t count;
count = snprintf(s, sizeof s, "n = %d, x = %.6f", n, x);
if (count > sizeof s) {
/* the string was truncated */
}
And to append multiple strings (say, if some are appended conditionally or repeatedly), you can use the methods in the other answers to keep track of the end of the target string.
So yes, it's possible to append formatted strings with strcat(). It's just not likely to be a good idea.
What the preferred method is, depends on what you are willing to use. Instead of doing all those manual (and potentially dangerous) string operations, I would use the GString data structure from GLib or GLib's g_strdup_print function. For your problem, GString provides the g_string_append_printf function.
Write your own wrapper for your need.
A call to this would look like this :-
result = universal_concatenator(4,result,"numbers are %d %f\n",5,16.045);
result = universal_concatenator(2,result,"tail_string");
You could define one function, that would take care of worrying about, if you need to use sprintf() or strcat(). This is what the function would look like :-
/* you should pass the number of arguments
* make sure the second argument is a pointer to the result always
* if non formatted concatenation:
* call function with number_of_args = 2
* else
* call function with number of args according to format
* that is, if five inputs to sprintf(), then 5.
*
* NOTE : Here you make an assumption that result has been allocated enough memory to
* hold your concatenated string. This assumption holds true for strcat() or
* sprintf() of your previous implementation
*/
char* universal_concaternator(int number_of_args,...)
{
va_list args_list;
va_start(args_list,number_of_args);
int counter = number_of_args;
char *result = va_arg(args_list, char*);
char *format;
if(counter == 2) /* it is a non-formatted concatenation */
{
result = strcat(result,va_arg(args_list,char*));
va_end(args_list);
return result;
}
/* else part - here you perform formatted concatenation using sprintf*/
format = va_arg(args_list,char*);
vsprintf(result + strlen(result),format,args_list);
va_end(args_list);
return result;
}
/* dont forget to include the header
* <stdarg.h> #FOR-ANSI
* or <varargs.h> #FOR-UNIX
*/
It should firstly, determine, which of the two it should call(strcat or sprintf), then it should make the call, and make it easy for you to concentrate on the actual logic of whatever you are working on!
Just ctrl+c code above and ctrl+v into your code base.
Note : Matt's answer is a good alternative for long strings. But for short string lengths(<250), this should do.

malloc double datatype with strlen

how do I allocate memory for strlen(esc) in a proper way? The temp and str are char datatypes.
double esc = t1.tv_sec+(t1.tv_usec/1000000.0);
strAll = malloc(strlen(temp) + strlen(str) + strlen(esc) + 1);
You cannot take strlen(esc). As I am sure the compiler has already told you, the argument to strlen() must be char *, you are passing it a double. Try first converting the double to array of char with snprintf().
You can find the length you need using snprintf. Passing '0' as the size will prevent is from writing any bytes, and it returns the number of bytes it would have needed.
size_t length = snprintf(0, 0, "%lf%s%lf", esc, temp, esc) + 1;
strAll = malloc(length);
snprintf(strAll, length, "%lf%s%lf", esc, temp, esc);
You'll need to convert esc to a string, probably with sprintf(). Then use the length from that in the malloc():
char buffer[32];
int n = snprintf(buffer, sizeof(buffer), "%.6f", esc);
if (n >= sizeof(buffer))
...handle overlong string problems (bail out)...
char *strAll = malloc(strlen(temp) + strlen(str) + n + 1);
if (strAll == 0)
...handle out of memory problem (bail out)...
sprintf(strAll, "%s%s%s", temp, str, buffer);
(I didn't check the length returned by sprintf() because 'it cannot go wrong'. You calculated the length of the component strings, and therefore, it will fill exactly the allocated space. If you do decide to check it, then preserve the length that is the argument to malloc() and test against that.)
Your code don't compile. strlen expects a string argument, that is a pointer to a sequence of char (like an array).
Perhaps you want something like
char buf[30];
double esc = somedoublefunction();
snprintf (buf, sizeof(buf), "%f", esc);
return strdup(buf);
of course you should care to later free the resulting pointer.
Try using one of the following if you're just trying to save all the data in one buffer:
sizeof(esc) or sizeof(double)
If you want to turn esc into a string. Otherwise, I would suggest using a fixed point format when converting to a string e.g. snprintf(buffer, 7, "%03.3f", esc);

String Padding in C

I wrote this function that's supposed to do StringPadRight("Hello", 10, "0") -> "Hello00000".
char *StringPadRight(char *string, int padded_len, char *pad) {
int len = (int) strlen(string);
if (len >= padded_len) {
return string;
}
int i;
for (i = 0; i < padded_len - len; i++) {
strcat(string, pad);
}
return string;
}
It works but has some weird side effects... some of the other variables get changed. How can I fix this?
It might be helpful to know that printf does padding for you, using %-10s as the format string will pad the input right in a field 10 characters long
printf("|%-10s|", "Hello");
will output
|Hello |
In this case the - symbol means "Left align", the 10 means "Ten characters in field" and the s means you are aligning a string.
Printf style formatting is available in many languages and has plenty of references on the web. Here is one of many pages explaining the formatting flags. As usual WikiPedia's printf page is of help too (mostly a history lesson of how widely printf has spread).
For 'C' there is alternative (more complex) use of [s]printf that does not require any malloc() or pre-formatting, when custom padding is desired.
The trick is to use '*' length specifiers (min and max) for %s, plus a string filled with your padding character to the maximum potential length.
int targetStrLen = 10; // Target output length
const char *myString="Monkey"; // String for output
const char *padding="#####################################################";
int padLen = targetStrLen - strlen(myString); // Calc Padding length
if(padLen < 0) padLen = 0; // Avoid negative length
printf("[%*.*s%s]", padLen, padLen, padding, myString); // LEFT Padding
printf("[%s%*.*s]", myString, padLen, padLen, padding); // RIGHT Padding
The "%*.*s" can be placed before OR after your "%s", depending desire for LEFT or RIGHT padding.
[####Monkey] <-- Left padded, "%*.*s%s"
[Monkey####] <-- Right padded, "%s%*.*s"
I found that the PHP printf (here) does support the ability to give a custom padding character, using the single quote (') followed by your custom padding character, within the %s format.
printf("[%'#10s]\n", $s); // use the custom padding character '#'
produces:
[####monkey]
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[BUFSIZ] = { 0 };
char str[] = "Hello";
char fill = '#';
int width = 20; /* or whatever you need but less than BUFSIZ ;) */
printf("%s%s\n", (char*)memset(buf, fill, width - strlen(str)), str);
return 0;
}
Output:
$ gcc -Wall -ansi -pedantic padding.c
$ ./a.out
###############Hello
You must make sure that the input string has enough space to hold all the padding characters. Try this:
char hello[11] = "Hello";
StringPadRight(hello, 10, "0");
Note that I allocated 11 bytes for the hello string to account for the null terminator at the end.
The argument you passed "Hello" is on the constant data area. Unless you've allocated enough memory to char * string, it's overrunning to other variables.
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
strncpy(buffer, "Hello", sizeof(buffer));
StringPadRight(buffer, 10, "0");
Edit: Corrected from stack to constant data area.
Oh okay, makes sense. So I did this:
char foo[10] = "hello";
char padded[16];
strcpy(padded, foo);
printf("%s", StringPadRight(padded, 15, " "));
Thanks!
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
int main() {
// your code goes here
int pi_length=11; //Total length
char *str1;
const char *padding="0000000000000000000000000000000000000000";
const char *myString="Monkey";
int padLen = pi_length - strlen(myString); //length of padding to apply
if(padLen < 0) padLen = 0;
str1= (char *)malloc(100*sizeof(char));
sprintf(str1,"%*.*s%s", padLen, padLen, padding, myString);
printf("%s --> %d \n",str1,strlen(str1));
return 0;
}
The function itself looks fine to me. The problem could be that you aren't allocating enough space for your string to pad that many characters onto it. You could avoid this problem in the future by passing a size_of_string argument to the function and make sure you don't pad the string when the length is about to be greater than the size.
One thing that's definitely wrong in the function which forms the original question in this thread, which I haven't seen anyone mention, is that it is concatenating extra characters onto the end of the string literal that has been passed in as a parameter. This will give unpredictable results. In the example call of the function, the string literal "Hello" will be hard-coded into the program, so presumably concatenating onto the end of it will dangerously write over code. If you want to return a string which is bigger than the original then you need to make sure you allocate it dynamically and then delete it in the calling code when you're done.
#include<stdio.h>
#include <string.h>
void padLeft(int length, char pad, char* inStr,char* outStr) {
int minLength = length * sizeof(char);
if (minLength < sizeof(outStr)) {
return;
}
int padLen = length - strlen(inStr);
padLen = padLen < 0 ? 0 : padLen;
memset(outStr, 0, sizeof(outStr));
memset(outStr, pad,padLen);
memcpy(outStr+padLen, inStr, minLength - padLen);
}

Resources