C writing to string (specific function asked) - c

I am kind of in a pinch with searching one specific function with return type int which changes the values of a char array (string) by taking exactly 5 parametres whereas the function must not be imported from any other library with an exception of stdio.h maybe.
The source looks like in following:
#include <stdio.h>
int main() {
char buffer [50];
int n;
n= // some function here ;
printf("%s",buffer,n);
return 0;
}
I have been looking into many functions, but none I knew of or found match the above requirement such that I'd appreciate the help of more knowledgeable people now. Thanks in advance.

You have to go with functions with variable argument lists.
Two such ones in stdio.h are:
int sprintf(char * restrict s, const char * restrict format, ...);
int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
Note: These functions do not exactly take five arguments as you specified in your question. They take a minimum number of arguments (2 & 3 respectively) but can go way beyond 5 arguments.
which changes the values of a char array (string)
The following does what you want to char array (info):
char info[60];
char name[] = "Christopher Westburry";
char designation[] = "Learner";
int reputation = 72;
sprintf(info, "Welcome %s to StackOverflow!\nDesignation: %s\nReputation: %d",
name, designation, reputation);
printf("%s", info);

Skimming Appendix B of the C Standard, I don't see anything that takes exactly 5 arguments and returns an int.
OTOH stdio.h is full of functions that return an int and take a variable number of arguments in the scanf and printf family. Once can contrive something. Since buffer is uninitialized, and the code wants to print it, presumably we're going to read something into it from stdin. That probably means some contrived scanf call.
#include <stdio.h>
int main() {
char buffer [50];
int n;
// Same as
// n = scanf("%40s", buffer);
n = scanf(
"%10s%10s%10s%10s",
buffer,
&buffer[10],
&buffer[20],
&buffer[30]
);
// printf("%s",buffer,n);
printf("'%s' %d\n",buffer,n);
return 0;
}
If that's the answer they expect, this exercise is pretty pointless.
Note that the printf in the original code has a bug where it's passed in too many arguments. Maybe that's a clue and this is supposed to be some clever use of Undefined Behavior?

Related

How to write a variadic function in C that takes integers and returns them all together in a dynamic string?

For example:
char* function(int n, ...); //prototype
main()
{
char* s;
s= function(3, 123, 456, 789);
printf("%s", s);
}
How do i write this function that will take integers and return a dynamic string of these integers? While trying to solve this, I have came across function itoa(); but I couldn't find enough things about it and there were very few examples using it, and also, should I dynamically allocate a character string in C and since (at least I think this is how it goes) I will be putting those integers in order one by one, should I use realloc for that string because its size will get bigger and bigger until im done? Do I use strcat to make basically a string of strings? And probably my biggest question, when and how in all that mess do I use function itoa()?
Function should return
"123456789"
EDIT: Thank you all for help, I took into consideration everything said and managed to solve this problem. Here is my final code (probably could have done a better job about memory management):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
char * function(int n, ...);
int main()
{
char* s;
s = function(3, 123, 456, 789);
printf("%s", s);
free(s);
s=function(9, 123,456,789,123,789, 12, 433, 553, 341);
printf("\n%s", s);
return 0;
}
char * function(int n, ...)
{
char str[100]={0};
char* res=0;
int i, br;
va_list args;
va_start(args, n);
for (i = 0; i < n; i++)
{
br=va_arg(args, int);
itoa(br, str, 10);
char* tmp=(char *)malloc(sizeof(str));
strcpy(tmp, res ? res : "");
strcat(tmp, str);
free(res);
res=tmp;
}
va_end(args);
return res;
}
C Algorithm
Determine worse cast size buffer for one int. Hint: As text, how long is INT_MIN?
Allocate a buffer that is n*worst_case + 1.
Set buf[0] = '\0';, size_t length_used = 0;
Walk the variadic arguments with va_start(), va_arg(), va_end() and friends. One at a time, convert using sprintf() into the end of the used buffer. Use the return value of the sprintf() to keep track of how far the used portion of the buffer has grown.
Perform a final realloc() to shrink and right-size the allocated buffer if desired.
Code code checks for errors in allocation and printing.
Take a walk and enjoy the week-end as spring is coming. (or maybe autumn?)
strcat() not needed.
itoa() not needed.
Advanced
To determine the bit width of value bits in an int (even if it has padding) use IMAX_BITS(INT_MAX).
To find the number of decimal digits given the bit width:
// bit_width * log2(10) rounded up
IMAX_BITS(m)*28/93 + 1
Account for the '-'.

How do I properly call the function I created to the main?

So I suck with functions and need to debug this. Im pretty sure the function ToPigLating does its job well at converting. However I just need help calling the function ToPigLatin inside of my main function. But when I try doing that I just get a bunch of error codes.
#include <stdlib.h>
#include <string.h>
#define LEN 32
char* ToPigLatin(char* word[LEN]){
char word[LEN];
char translation [LEN];
char temp [LEN];
int i, j;
while ((scanf ("%s", word)) != '\0') {
strcpy (translation, word);
//just pretend I have all the work to convert it in here.
} // while
}
int main(){
printf("Enter 5 words: ");
scanf("%s", word);
ToPigLatin();
}```
Roughly, variables only exist within the function they're declared in. The word in ToPigLatin exists only within ToPigLatin. It is not available in main. This lets us write functions without worrying about all the rest of the code.
You need to declare a different variable in main, it can also be called word, to store the input and then pass that into ToPigLatin.
Let's illustrate with something simpler, a function which doubles its input.
int times_two(int number) {
return number * 2;
}
We need to give times_two a number.
int main() {
// This is different from "number" in times_two.
int number = 42;
// We have to pass its value into time_two.
int doubled = times_two(number);
printf("%d doubled is %d\n", number, doubled);
}
Your case is a bit more complicated because you're working with input and memory allocation and arrays. I'd suggest just focusing on arrays and function calls for now. No scanf. No strcpy.
For example, here's a function to print an array of words.
#include <stdio.h>
// Arrays in C don't store their size, the size must be given.
void printWords(const char *words[], size_t num_words) {
for( int i = 0; i < num_words; i++ ) {
printf("word[%d] is %s.\n", i, words[i]);
}
}
int main(){
// This "words" variable is distinct from the one in printWords.
const char *words[] = {"up", "down", "left", "right"};
// It must be passed into printWords along with its size.
printWords(words, 4);
}
ToPigLatingToPigLating function expects to have a parameter like ToPigLating("MyParameter");
Hello there icecolddash.
First things first, there are some concepts missing. In main section:
scanf("%s", word);
You're probably trying to read a string format and store in word variable.
In this case, you should have it on your declaration scope. After some adjustment, it will look like this:
int main(){
char word[LEN];
As you defined LEN with 32 bytes maximum, your program will not be allowed to read bigger strings.
You're also using standard input and output funcitions as printf, and so you should ever include stdio.h, thats the header which cointains those prototypes already declared, avoiding 'implicit declaration' compiling warnings.
Next issue is how you're declaring your translation function, so we have to think about it:
char* ToPigLatin(char* word[LEN])
In this case, what you wrote:
ToPigLatin is a funcion that returns a char pointer, which means you want your function to probably return a string. If it makes sense to you, no problem at all. Although we got some real problem with the parameter char* word[LEN].
Declaring your variable like this, assume that you're passing an array of strings as a parameter. If I got it right, you want to read all five words in main section and translate each one of them.
In this case I suggest some changes in main function, for example :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 32
#define MAX_WORDS 5
char *globalname = "translated";
char* ToPigLatin(char* word){
char *translation = NULL;
//Translation work here.
if ( !strcmp(word, "icecolddash") ){
return NULL;
}
translation = globalname;
return translation;
}
int main(){
char word[LEN];
char *translatedword;
int i;
printf("Enter 5 words: \n");
for ( i=0; i < MAX_WORDS; i++ ){
fgets(word, sizeof(word), stdin);
strtok(word, "\n"); // Just in case you're using a keyboard as input.
translatedword = ToPigLatin(word);
if ( translatedword != NULL ){
//Do something with your translation
//I'll just print it out as an example
printf("%s\n", translatedword);
continue;
}
// Generic couldn't translate message
printf("Sorry, I know nothing about %s\n", word);
}
return 0;
}
The above code translate every word in a fixed word "translated".
In case of reading the exact input "icecolddash", the program will output a generic error message, simulating some problem on translation process.
I hope this help you out with your studies.
There are a few things that I see.
#include <stdio.h>
#include <stdlib.h>
char* ToPigLatin(char* word){
printf(word);
return word;
}
int main(){
printf("Enter 5 words: ");
// declare the variable read into by scanf
char * word = NULL;
scanf("%s", word);
//Pass the variable into the function
ToPigLatin(word);
// Make sure you return an int from main()
return 0;
}
I left some comments in the code with some specific details.
However, the main thing that I would like to call out is the style of the way you're writing your code. Always try to write small, testable chunks and build your way up slowly. Try to get your code to compile. ALWAYS. If you can't run your code, you can't test it to figure out what you need to do.
As for the char ** comment you left on lewis's post, here is some reading you may find useful in building up your intuition:
https://www.tutorialspoint.com/what-does-dereferencing-a-pointer-mean-in-c-cplusplus
Happy coding!

How to return a string to main function?

I am trying to write code to implement strchr function in c. But, I'm not able to return the string.
I have seen discussions on how to return string but I'm not getting desired output
const char* stchr(const char *,char);
int main()
{
char *string[50],*p;
char ch;
printf("Enter a sentence\n");
gets(string);
printf("Enter the character from which sentence should be printed\n");
scanf("%c",&ch);
p=stchr(string,ch);
printf("\nThe sentence from %c is %s",ch,p);
}
const char* stchr(const char *string,char ch)
{
int i=0,count=0;
while(string[i]!='\0'&&count==0)
{
if(string[i++]==ch)
count++;
}
if(count!=0)
{
char *temp[50];
int size=(strlen(string)-i+1);
strncpy(temp,string+i-1,size);
temp[strlen(temp)+1]='\0';
printf("%s",temp);
return (char*)temp;
}
else
return 0;
}
I should get the output similar to strchr function but output is as follows
Enter a sentence
i love cooking
Enter the character from which sentence should be printed
l
The sentence from l is (null)
There are basically only two real errors in your code, plus one line that, IMHO, should certainly be changed. Here are the errors, with the solutions:
(1) As noted in the comments, the line:
char *string[50],*p;
is declaring string as an array of 50 character pointers, whereas you just want an array of 50 characters. Use this, instead:
char string[50], *p;
(2) There are two problems with the line:
char *temp[50];
First, as noted in (1), your are declaring an array of character pointers, not an array of characters. Second, as this is a locally-defined ('automatic') variable, it will be deleted when the function exits, so your p variable in main will point to some memory that has been deleted. To fix this, you can declare the (local) variable as static, which means it will remain fixed in memory (but see the added footnote on the use of static variables):
static char temp[50];
Lastly, again as mentioned in the comments, you should not be using the gets function, as this is now obsolete (although some compilers still support it). Instead, you should use the fgets function, and use stdin as the 'source file':
fgets(string, 49, stdin);/// gets() has been removed! Here, 2nd argument is max length.
Another minor issue is your use of the strlen and strncpy functions. The former actually returns a value of type size_t (always an unsigned integral type) not int (always signed); the latter uses such a size_t type as its final argument. So, you should have this line, instead of what you currently have:
size_t size = (strlen(string) - i + 1);
Feel free to ask for further clarification and/or explanation.
EDIT: Potential Problem when using the static Solution
As noted in the comments by Basya, the use of static data can cause issues that can be hard to track down when developing programs that have multiple threads: if two different threads try to access the data at the same time, you will get (at best) a "data race" and, more likely, difficult-to-trace unexpected behaviour. A better way, in such circumstances, is to dynamically allocate memory for the variable from the "heap," using the standard malloc function (defined in <stdlib.h> - be sure to #include this header):
char* temp = malloc(50);
If you use this approach, be sure to release the memory when you're done with it, using the free() function. In your example, this would be at the end of main:
free(p);

How does printf() function treat the strings returned by functions using global buffers?

I have written a small code that prints the current date with a specific format. To return each data of the date (day of the week, day of the month, name of the month, etc.), I use functions of type const char * that pass the data as a string to a variable that serves as a buffer and then pass the buffer to the main function.
The following code represents the operation of my program in a very simple way:
#include <stdio.h>
#include <string.h>
char
buff[16];
const char
*printStr1 (char *str1)
{
strncpy(buff, str1, sizeof(str1));
return buff;
};
const char
*printStr2 (char *str2)
{
strncpy(buff, str2, sizeof(str2));
return buff;
};
int
main()
{
printf("%s%s", printStr1("foo"), printStr2("bar"));
return 0;
}
My issue is this: when passing each data to the buffer and returning it to the main function, the last two data are the same (the last data is not printed, instead it is printed what was already in the buffer, that is, the second last data).
This only happens when I use a single printf() function to show all the data, as in the example above. If I do not use a buffer to return the data (I directly return the argument passed to the function) or use a printf() for every data , everything is executed correctly.
P.S.: I tried to solve this using functions like memset() to clean the buffer, but it does not work, the only thing I can do is use a different buffer for each data (for each function).
I hope I have expressed my problem well.
Besides the sizeof issue (that you're overlooking because your strings are small), your issue isn't related to printf
The code first evaluates the arguments, then passes them to printf. The last evaluated argument "wins" and printf gets the same argument twice.
To use only one local buffer, split your printf call:
printf("%s%s", printStr1("foo"), printStr2("bar"));
could be rewritten to:
printf("%s", printStr1("foo"));
printf("%s", printStr2("bar"));
once printed the value can change it doesn't matter :)
Since C doesn't have a garbage collector or string objects, you cannot just allocate separate buffers and return them to pass to printf else you'd get memory leaks, so in C there's no smart & readable solution for such issues.
That said, in one C project I made, I used a revolving list of strings (several buffers, first in, first out). Make it 10 buffers, and you can use up to 10 arguments in the same function and it will work properly.
This code:
printf("%s%s", printStr1("foo"), printStr2("bar"));
is equivalent to this:
const char *p1 = printStr1("foo");
const char *p2 = printStr2("bar");
printf("%s%s", p1, p2);
or this (depending on the compiler):
const char *p2 = printStr2("bar");
const char *p1 = printStr1("foo");
printf("%s%s", p1, p2);
Now it should be clear why you're getting the output you get.
In addition to #Jean-François Fabre good answer, ...
To print printStr1("foo"), printStr2("bar") with 1 printf(), separate buffers are needed.
Since C99, code can use compound literals.
#include <stdio.h>
#include <string.h>
#define PRINT_N 16
const char *printStr1(char *dest, size_t n, const char *str) {
snprintf(dest, n, "%d %s\n", 1, str);
return dest;
}
const char *printStr2(char *dest, size_t n, const char *str) {
snprintf(dest, n, "%d %s\n", 2, str);
return dest;
}
// compound literals -------------v-----------------v
#define PRINT_STR1(src) printStr1((char [PRINT_N]){0}, PRINT_N, (src))
#define PRINT_STR2(src) printStr2((char [PRINT_N]){0}, PRINT_N, (src))
int main() {
printf("%s%s\n", PRINT_STR1("foo"), PRINT_STR2("bar"));
printf("%s%s%s%s\n", PRINT_STR1("foo"), PRINT_STR2("bar"), PRINT_STR2("foo"), PRINT_STR1("bar"));
}
Output
1 foo
2 bar
1 foo
2 bar
2 foo
1 bar

Char arrays and scanf function in C

I expected to get errors in following code, but I did not. I did not use & sign. Also I am editing array of chars.
#include <stdio.h>
int main()
{
char name[10] ="yasser";
printf("%s\n",name);
// there is no error ,
// trying to edit array of chars,
// also did not use & sign.
scanf("%s",name);
// did not use strcpy function also.
printf("%s\n",name);
return 0;
}
I expected to get errors in following code, but I did not.I did not use & sign.
scanf("%s",name);
That's totally ok as name is already the address of the character array.
It sounds like you have several questions:
calling scanf("%s", name) should have given an error, since %s expects a pointer and name is an array? But as others have explained, when you use an array in an expression like this, what you always get (automatically) is a pointer to the array's first element, just as if you had written scanf("%s", &name[0]).
Having scanf write into name should have given an error, since name was initialized with a string constant? Well, that's how it was initialized, but name really is an array, so you're free to write to it (as long as you don't write more than 10 characters into it, of course). See more on this below.
Characters got copied around, even though you didn't call strcpy? No real surprise, there. Again, scanf just wrote into your array.
Let's take a slightly closer look at what you did write, and what you didn't write.
When you declare and initialize an array of char, it's completely different than when you declare and initialize a pointer to char. When you wrote
char name[10] = "yasser";
what the compiler did for you was sort of as if you had written
char name[10];
strcpy(name, "yasser");
That is, the compiler arranges to initialize the contents of the array with the characters from the string constant, but what you get is an ordinary, writable array (not an unwritable, constant string constant).
If, on the other hand, you had written
char *namep = "yasser";
scanf("%s", namep);
you would have gotten the problems you expected. In this case, namep is a pointer, not an array. It's initialized to point to the string constant "yasser", which is not writable. When scanf tried to write to this memory, you probably would have gotten an error.
When you pass arrays to functions in C, they decay to pointers to the first item.
Therefore for:
char name[] ="yasser";
scanf("%s", name) is the same as scanf("%s", &name[0]) and either of those invocations should send shivers down your spine, because unless you control what's on your stdin (which you usually don't), you're reading a potentially very long string into a limited buffer, which is a segmentation fault waiting to happen (or worse, undefined behavior).
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
char *myName = (char *) calloc(10, sizeof(char));
*(myName)='K'; *(myName+1)='h'; *(myName+2)='a'; *(myName+3)='l'; *(myName+4)='i'; *(myName+5)='d';
printf("%s\n",myName);
scanf("%s",myName);
printf("%s\n",myName);
return (EXIT_SUCCESS);
}
#include <stdio.h>
#include <string.h>
int main()//fonction principale
{
char name[10] ="yasser";
int longeur=0;
printf("%s\n",name);
scanf("%s",name);
longeur = strlen(name);
for (int i=0;i<longeur;i++) {
printf("%c",*(name+i));
}
return 0;}

Resources