I am making a program that needs to receive the following input:
{Time1 Time2 Appointment} as {hour1:minute1 hour2:minute2 Appointment}
The "Appointment" is a useless string input and i would like to ignore it
scanf("%d:%d %d:%d",&hour1,&minute1,&hour2,&minute2);
I am able to get the hours and minutes but after that i can't use "scanf" again, how can i just ignore the "Appointment" input?
You can do %*s thing, and also you can use an input buffer after the first scanf. Something like this:
int minute1 = 0, hour1 = 0, minute2 = 0, hour2 = 0;
char buffer[100];
scanf("%d:%d %d:%d %99[^\n]s",&hour1, &minute1 ,&hour2 ,&minute2, buffer);
printf("%d:%d %d:%d\n", hour1, minute1, hour2, minute2);
Related
I have a problem wherein I want to call sprintf(or similar function) multiple times for it to replace the format specifier with the data values one at a time,
For E.g.: char *str = "Temperature is %f, Humidity is %d, wait for %d secs";
Now I receive the argument data in multiple variables and I want to be able to call
float temp = 23.45;
char humidity = 87;
int time = 3;
sprintf(buf, str, temp);
sprintf(buf, str, humidity);
sprintf(buf, str, time);`
However we see the first call to sprintf itself will replace first %f with 23.45 and other format specifiers with garbage or 0. What I expect in str after first sprintf call is
"Temperature is 23.45, Humidity is %d, wait for %d secs"
So I know I cannot use sprintf or snprintf for this, is there another string library call which does what I a expecting?
I tried this in online gdb and sprintf is not the function I am looking for.
It seems to me like you probably want to call
sprintf(buf, str, temp, humidity, time);
This should result in "Temperature is 23.45, Humidity is 87, wait for 3 secs", all in one go.
However, if calling sprintf multiple times is important to you, for some reason, you can simply escape the percent signs an appropriate number of times, so that each sprintf call evaluates one more escape. By which I mean,
char *str = "Temperature is %f, Humidity is %%d, wait for %%%%d secs";
float temp = 23.45;
char humidity = 87;
int time = 3;
sprintf(buf, str, temp); // "Temperature is 23.45, Humidity is %d, wait for %%d secs"
sprintf(buf2, buf, humidity); // "Temperature is 23.45, Humidity is 87, wait for %d secs"
sprintf(buf3, buf2, time); // "Temperature is 23.45, Humidity is 87, wait for 3 secs"
You CAN use sprintf().
Try something like this:
float temp = 23.45;
char humidity = 87;
int time = 3;
char *at = buf;
at += sprintf( at, "Temp: %.1f ", temp );
at += sprintf( at, "Humidity: %d ", (int)humidity );
at += sprintf( at, "Time: %d", time );
puts( buf );
It's up to you to make sure that buf[] is large enough to hold the entire string.
It's a nice feature of this simplicity that the 'humidity' field (or another) could be easily suppressed with an appropriate if().
You can use %n to track output length. You also must separate the format string into its constituent parts.
int n1, n2;
sprintf( buf, "Temperature is %f, %n", temp, &n1 );
sprintf( buf+n1, "Humidity is %d, %n", humidity, &n2 );
sprintf( buf+n1+n2, "wait for %d secs", time );
You could also just use strchr():
*buf = 0;
sprintf( strchr( buf, 0 ), "Temperature is %f, ", temp );
sprintf( strchr( buf, 0 ), "Humidity is %d, ", humidity );
sprintf( strchr( buf, 0 ), "wait for %d secs", time );
Honestly, though, Fe2O3’s answer is simplest, heh. 😉
I've been working on this project that deals with an input file that looks like the following:
A 0.0345
B 0.3945
...
Z 0.2055
Basically, I'm reading each line, after reading the line, I want to pull only the double out of the string. I'm trying to use strtod() and everyone's examples seem to use it perfectly fine but in my example, it only returns 0.
Here is my code:
for (count = 0; count < 26; count++)
{
char buffer[100]; /* Buffer for the line read by fgets */
char *letters; /* Stores the string calculated by strtod */
double relFreq = 0.0;
if (fgets(buffer, 100, stream) != NULL)
{
relFreq = (double)strtod(buffer, &letters); /* Since the format is A 0.0000, we're just grabbing the double */
*(sampleOne + count) = relFreq; /* Add the relFreq to the array */
}
}
Through the use of a debugger, buffer has the correct data, for instance A 0.0345\n but when strtod() returns a value it's always 0. Any help would be appreciated!
Since the first character is non-numeric, strtod should be returning letters equal to buffer (the first character is invalid), indicating that nothing has been read.
You should be able to fix this by passing &buffer[2], where the number starts:
relFreq = strtod(&buffer[2], &letters);
Demo.
I'm not sure why you think that strtod will ignore the leading letter on your lines, but it will not. You'll need to do something like this:
relFreq = (double) strtod(&buffer[1], &letters);
And since you are not using letters:
relFreq = (double) strtod(&buffer[1], NULL);
You could use sscanf. For example
#include <stdio.h>
int main(void)
{
char *s = "A 0.0345\n";
char c;
double d;
sscanf( s, "%c %lf", &c, &d );
printf( "%f\n", d );
return 0;
}
The output os
0.034500
As for your code then you could at first to find a digit in the buffer and apply function strtod to the pointer that points to the found digit provided that the first field in the buffer is always a non-digit.
I tried using atoi but I can only get to the 500 that way. Not sure where to go from here.
You can use strtol to "tokenize" a chain of whitespace-separated integers:
int a, b;
char src[] = "500 600";
char *tmp = src;
// The first call to strtol parses 500
a = strtol(tmp, &tmp, 10);
// The call looks the same, but tmp now points at the space between 500 and 600
// The next call to strtol skips the space, and parses 600
b = strtol(tmp, &tmp, 10);
Obviously, this code is skeletal, and skips the relevant checks. See documentation for the precise information on how strtol handles various unexpected situations.
Read the entire string using fgets.
Tokenize the string based on the space delimeter using strtok.
Convert the token to the integer.
If string has more characters, go to step 2.
Using sscanf will be simple.
An example to use sscanf is as below:
char str[] = "500 600";
int a, b;
if(sscanf(str, "%d%d", &a, &b)==2) {
// OK
} else {
// failed to parse
}
If you do not need to test the sscanf has failed or not, write as below:
sscanf(str, "%d%d", &a, &b);
char &s = "500 600";
int x, y;
if (2 == sscanf(s, "%d %d", &x, &y))
{
/* Everything is ok */
}
else
{
/* Have another go! */
}
should do the trick
I am writing a c library but before I want to test the functions. So, I do the following:
int main(void)
{
GString *msg = NULL;
msg = g_string_sized_new(256);
printf ("Insert a string (255 characters at most): ");
do_fgets((char *) msg->str, (size_t) msg->len, stdin);
printf("msg->allocated_len = %u \n", (size_t) msg->allocated_len);
printf("msg->len = %u \n", (size_t) msg->len);
return 0;
}
the compile is ok, but the program prints the following:
msg->allocated_len = 512
msg->len = 0
Why this? Is there any other way to get interactive input from the user using glib functions?
I'll be grateful if somebody could help me!
I'm assuming the do_fgets is your own function wrapping fgets, anyway...
Your code is failing since it is trying to read 0 bytes (the initial value of msg->len). Additionally, msg->len is never updated (it is passed to do_fgets by value).
Resurection!
I think I've found the solution to my question. What I did is to read the input to a buffer and then assign the buffer to the struct member src an everything is ok. That's the code roughly:
int main(void)
{
GString *msg = NULL;
gchar *p;
gchar buf[256];
msg = g_string_sized_new(256);
printf ("Enter a message (255 characters at most): ");
p = fgets(buf, sizeof(buf), stdin);
g_string_assign(msg, buf);
printf("msg->str = [%s] \n", (char *) msg->str);
printf("msg->len = %u \n", (size_t) msg->len);
printf("msg->allocated_len = %u \n", (size_t) msg->allocated_len);
return 0;
}
So it prints out:
msg->str = [this is my message]
msg->len = 19
msg->allocated_len = 512
The only strange is why the allocated_len is 512 instead of 256.
Thanks to everyone for the reply...
Resurrection, debugging led me to the next solution. Thank you Hasturkun for your help, I wanted to post my answer since yesterday but new members cannot answer their questions before 8 hours pass. The solution is this:
int main(void)
{
GString *msg = NULL;
gchar *p;
gchar buf[256];
msg = g_string_sized_new(256);
printf ("Enter a message (255 characters at most): ");
p = fgets(buf, sizeof(buf), stdin);
g_string_assign(msg, buf);
printf("msg->str = [%s] \n", (char *) msg->str);
printf("msg->len = %u \n", (size_t) msg->len);
printf("msg->allocated_len = %u \n", (size_t) msg->allocated_len);
}
And it prints out everything very well...
Thank you all for your comments!
char *feedtime = "0:0";
String interval = "6";
char* convert(char* x, String y){
int hour;
int minute;
sscanf(x, "%d:%d", &hour, &minute);
char buf[5];
if (y == "6"){
if (hour > 17){
hour = (hour+6)%24;
snprintf(buf, 5, "%d%s", hour, ":0");
}
if (hour < 18){
hour = hour + 6;
snprintf(buf, 5, "%d%s", hour, ":0\0");
}
}
buf [5] = '\0';
return buf;
}
When I execute convert(time, interval);
the serial monitor returns the correct value but adds a ' or another symbol to it.
Any ideas why?
I updated my code from what people said, however I still get the same issue?
You are returning a pointer to a stack variable. This is wrong. Once the function exits the stack space used by 'buf' is undefined.
You need an extra character in your buffer. You only have a 4 character array, but you need 5 characters (2 for the hour, 2 for the :0, and 1 for the trailing 0). You also need to null terminate the string when you are done.
and what jcopenha says.
Your strings aren't properly zeroterminated. Increase the size of buf.