I'm doing a small app for evaluating and analyzing transfer functions. As boring as the subject might seem to some, I want it to at least look extra cool and pro and awesome etc... So:
Step 1: Gimme teh coefficients! [A bunch of numbers]
Step 2: I'll write the polynomial with its superscripts. [The bunch of numbers in a string]
So, I write a little C parser to just print the polynomial with a decent format, for that I require a wchar_t string that I concatenate on the fly. After the string is complete I quickly try printing it on the console to check everything is ok and keep going. Easy right? Welp, I ain't that lucky...
wchar_t *polynomial_description( double *polyArray, char size, char var ){
wchar_t *descriptionString, temp[100];
int len, counter = 0;
SUPERSCRIPT superscript;
descriptionString = (wchar_t *) malloc(sizeof(wchar_t) * 2);
descriptionString[0] = '\0';
while( counter < size ){
superscript = polynomial_utilities_superscript( size - counter );
len = swprintf(temp, 100, L"%2.2f%c%c +", polyArray[counter], var, superscript);
printf("temp size: %d\n", len);
descriptionString = (wchar_t *) realloc(descriptionString, sizeof(wchar_t) * (wcslen(descriptionString) + len + 1) );
wcscat(descriptionString, temp);
counter++;
}
//fflush(stdout); //Already tried this
len = wprintf(L"%ls\n", descriptionString);
len = printf("%ls**\n", descriptionString);
len = fprintf(stdout, "%ls*\n", descriptionString);
len = printf("FFS!! Print something!");
return descriptionString;
}
During the run we can see temp size: 8 printed the expected number of times ONLY WHILE DEBUGGING, if I run the program I get an arbitrary number of prints each run. But after that, as the title states, wprintf, printf and fprintf don't print anything, yet len does change its size after each call.
In the caller function, (application:(UIApplication *)application didFinishLaunchingWithOptions:, while testing) I put an NSLog to print the return string, and I dont get ANYTHING not even the Log part.
What's happening? I'm at a complete loss.
Im on XCode 4.2 by the way.
What's the return value from printf/wprintf in the case where you think it's not printing anything? It should be returning either -1 in the case of a failure or 1 or more, since if successful, it should always print at least the newline character after the description string.
If it's returning 1 or more, is the newline getting printed? Have you tried piping the output of your program to a hex dumper such as hexdump -C or xxd(1)?
If it's returning -1, what is the value of errno?
If it turns out that printf is failing with the error EILSEQ, then what's quite likely happening is that your string contains some non-ASCII characters in it, since those cause wcstombs(3) to fail in the default C locale. In that case, the solution is to use setlocale(3) to switch into a UTF-8 locale when your program starts up:
int main(int argc, char **argv)
{
// Run "locale -a" in the Terminal to get a list of all valid locales
setlocale(LC_ALL, "en_US.UTF-8");
...
}
Related
I am trying to send values from ADC through USB using "CDC_Transmit_FS()"
On the receiving side, I am receiving data using readline() and decoding the 'string' to 'int'
The code works fine but occasionally I receive for example, b'\x00234\n' instead of b'1234\n', which raises decoding error.
Do you know why does '\x' appear?
One more question is: Is there any smarter method to send ADC values through USB instead of converting int values to string?
I want to make the transmission faster.
thanks in advance!
uint32_t adcbuff[sample];
char endofpacket[5] = {'9', '9', '9', '9', '\n'};
char txbuff[sample*5];
while(1)
{
HAL_ADC_Start_DMA(&hadc2,(uint32_t*)adcbuff, sample);
for(i = 0; i < sample; i++)
{
sprintf (tempbuff, "%u\n", ((adcbuff[i] * 5000) / 0xFFFF)-2000);
strcat( txbuff,tempbuff);
}
strcat( txbuff,endofpacket);
CDC_Transmit_FS( (uint8_t*)txbuff, strlen(txbuff));
strcpy(txtbuff,"");
}
not enough rep to post as a comment
Usually \x is an indication of a hexadecimal value. Could it be that a non alphanumeric value is being received?
For troubleshooting, I would temporarily change
sprintf (tempbuff, "%u\n", ((adcbuff[i] * 5000) / 0xFFFF)-2000); to
sprintf (tempbuff, "%s\n", ((adcbuff[i] * 5000) / 0xFFFF)-2000); to see what kind of characters are being sent over. (Maybe sprintf to a tmp file instead.)
b'\x00234\n' - This means that first byte is 0! Not ASCII 0 = 0x30, but just 0.
Probably this is effect of strcat - after concatenating this function adds '\0' at the end of string.
Instead of using sprintf, just redirect stdout to USB-CDC and use printf:
int _write(int file, char *ptr, int len)
{
UNUSED(file);
CDC_Transmit_FS((uint8_t*)ptr, len);
while (hcdc->TxState != 0);
return len;
}
If you want to send all at once use setvbuf for stdout with _IOFBF and call fflush(stdout);
I'm just an amateur programmer...
And when reading, for the second time, and more than two years apart, kochan's "Programming in Objective-C", now the 6th ed., reaching the pointer chapter i tried to revive the old days when i started programming with C...
So, i tried to program a reverse C string function, using char pointers...
At the end i got the desired result, but... got also a very strange behavior, i cannot explain with my little programming experience...
First the code:
This is a .m file,
#import <Foundation/Foundation.h>
#import "*pathToFolder*/NSPrint.m"
int main(int argc, char const *argv[])
{
#autoreleasepool
{
char * reverseString(char * str);
char *ch;
if (argc < 2)
{
NSPrint(#"No word typed in the command line!");
return 1;
}
NSPrint(#"Reversing arguments:");
for (int i = 1; argv[i]; i++)
{
ch = reverseString(argv[i]);
printf("%s\n", ch);
//NSPrint(#"%s - %s", argv[i], ch);
}
}
return 0;
}
char * reverseString(char * str)
{
int size = 0;
for ( ; *(str + size) != '\0'; size++) ;
//printf("Size: %i\n", size);
char result[size + 1];
int i = 0;
for (size-- ; size >= 0; size--, i++)
{
result[i] = *(str + size);
//printf("%c, %c\n", result[i], *(str + size));
}
result[i] = '\0';
//printf("result location: %lu\n", result);
//printf("%s\n", result);
return result;
}
Second some notes:
This code is compiled in a MacBook Pro, with MAC OS X Maverick, with CLANG (clang -fobjc-arc $file_name -o $file_name_base)
That NSPrint is just a wrapper for printf to print a NSString constructed with stringWithFormat:arguments:
And third the strange behavior:
If I uncomment all those commented printf declarations, everything work just fine, i.e., all printf functions print what they have to print, including the last printf inside main function.
If I uncomment one, and just one, randomly chosen, of those comment printf functions, again everything work just fine, and I got the correct printf results, including the last printf inside main function.
If I leave all those commented printf functions as they are, I GOT ONLY BLANK LINES with the last printf inside main block, and one black line for each argument passed...
Worst, if I use that NSPrint function inside main, instead of the printf one, I get the desired result :!
Can anyone bring some light here please :)
You're returning a local array, that goes out of scope as the function exits. Dereferencing that memory causes undefined behavior.
You are returning a pointer to a local variable of the function that was called. When that function returns, the memory for the local variable becomes invalid, and the pointer returned is rubbish.
I'm developing a console app in Objective-C. I've got it working, but when manually testing edge cases, I found a strange behavior that I can't explain.
Basically, I've set up scanf() in a loop, and when the user types invalid info, it prints an "invalid option" message. Then, if the input is less than 9 characters long, it goes through the loop again as intended. But, if the input is 9 characters or longer, it gives a EXC_BAD_ACCESS error on a certain line.(This error doesn't happen if I comment out said line.)I can't figure out any reason why 8 vs 9 characters being read would cause this error. Any ideas?
Below are the two methods that I figure are relevant, with a comment on the line throwing the error. If you think other referenced code may be causing this, let me know and I'll add that code.
-(void)startMenu {
printf("\nGAME OPTIONS\n| WinningScore = %d (w) | Name = %s (n) | Back (b) |\n",
_options.winningScore, [_options.name UTF8String]);
}
-(void)start {
char selectedOption;
char w = 'w';
char n = 'n';
char b = 'b';
while(YES) {
[self startMenu]; // This line gets the EXC_BAD_ACCESS error
// if the user puts in 9 or more characters.
// If it is commented out, then no error is thrown.
scanf("%s", &selectedOption);
if(selectedOption == w) {
[self setWinningScore];
} else if(selectedOption == n) {
[self setName];
} else if(selectedOption == b) {
break;
} else {
printf("'%s' is not a valid option.\n", &selectedOption);
}
}
}
It this was C (and the post is tagged C) I'd suggest:
char selectedOption;
....
scanf(" %c", &selectedOption);
...
printf("'%c' is not a valid option.\n", selectedOption);
The failure showing up after a 9 charterer input is serendipity. scanf("%s", &selectedOption); is certainly wrong for reading a single character. Any input starts causing problems. Use the matching format specifier and variable.
[Edit]
A C-like solution.
If more than 1 char is desire for input, use the idea put forth by #Devolus. Example:
char selectedOption[10];
if (fgets(selectedOption, sizeof selectedOption, stdin) == NULL)
Handle_EOForIOerror();
// Get rid of potential trailing \n if desired.
size_t len = strlen(selectedOption);
if (len > 0 && selectedOption[len-1] == '\n') selectedOption[--len] = '\0';
You should use fgets instead of scanf here, as you can limit the number of characters in the buffer.
scanf is potentially unsafe because the buffer can be exceeded.
I'm new to Objective-C, and this is really my first program that is interactive. I've been learning for about 2 weeks now.
So, my question is: typically I've noticed when you have multiple scanf's in a row, they each wait for input - however in this situation, where I ask for account owner name, and balance - it fires both NSLog functions instead of waiting for the first input.
Here is my main:
int main(int argc, char* argV[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
bank *columbiaBank = [[bank alloc] init];
int iteration = 0;
while (true) {
int selection = 0;
NSLog(#"\n1. Add Account \n2. Remove Account \n3. Modify Account \nWhat would you like to do?:");
scanf("%i", &selection);
if (selection == 1) {
NSLog(#"\nEnter account owner:");
char accountOwner;
scanf("%c", &accountOwner);
NSLog(#"\nEnter opening balance:");
float openingBalance;
scanf("%f", &openingBalance);
// create and add new account
bankAccount *newAccount = [[bankAccount alloc] initWithProps:[NSString stringWithFormat:#"%c", accountOwner] :[NSString stringWithFormat:#"%i", iteration] :openingBalance];
[columbiaBank addAccount:newAccount];
[newAccount release];
NSLog(#"\nAccount successfully added!");
} else if (selection == 2) {
NSLog(#"\nEnter account id:");
int accountId;
scanf("%i", &accountId);
// remove account
[columbiaBank removeAccount:[NSString stringWithFormat:#"%i", accountId]];
NSLog(#"\nAccount successfully removed!");
} else if (selection == 3) {
NSLog(#"\nThe bank currently has %i accounts.", columbiaBank.totalAccounts);
NSLog(#"\nThe bank's current balance from all accounts is $%f", columbiaBank.totalBankBalance);
NSLog(#"\n-- Output of all account info --");
[columbiaBank printAccounts];
} else {
NSLog(#"You did not enter a valid action.");
}
iteration++;
}
[columbiaBank release];
[pool drain];
return false;
}
Other users already said everything about it. The scanf inserts a new line "\n" automatically in the buffer that is passed to the next scanf. This is because any unwritten data is written in the next stream.
I want to add that you can use fflush to clear the stream buffer, in this case you want to use
scanf("%i", &selection);
fflush(stdin)
to clear the buffer of stdin (the console input) after every scanf.
Edit: I didn't know that, but As #Peter Kowalski said the use of fflush(stdin), for input stream, should be avoided because it has an undefined behaviour for input streams.
Cprograming.com FAQ > Why fflush(stdin) is wrong.
But it seems that there is not a guaranteed method to flush the input stream in C.
Cprograming.com FAQ > Flush the input stream
I know that in C++ a standard way is to use cin.ignore() after cin >> selection but I don't know how this can be done in C. Maybe some more experienced user can give some insight on what is happening with fflush(stdin).
*[Note: If you are going to use Objective-C you might wish to use input conversion methods from Cocoa rather than mix Cocoa (NSLog) and stdio (scanf). But that doesn't answer your question...]
When parsing integers, floats and even strings scanf skips whitespace - e.g. spaces, tabs, end of line, etc. - and every input line ends with at least an end of line (which may be a carriage return, line feed, or both depending on the system). This means that after reading your first integer there is still, at least, an end of line in the input and the attempt to read a character will return it - hence no wait for input. To discard the remaining, unused, input you can use fpurge. E.g.:
#include <stdio.h>
int main(int argc, char* argV[])
{
int selection = 0;
fputs("\n1. Add Account \n2. Remove Account \n3. Modify Account \nWhat would you like to do?: ", stdout);
scanf("%i", &selection);
if (selection == 1)
{
fputs("\nEnter account owner: ", stdout);
fpurge(stdin); // skip any input left in the buffer as %c takes the very next character and does not skip whitespace
char accountOwner;
scanf("%c", &accountOwner);
fputs("\nEnter opening balance: ", stdout);
float openingBalance;
scanf("%f", &openingBalance);
printf("%c - %f\n", accountOwner, openingBalance);
}
}
Note that reading in character strings does skip whitespace, so if your account owner was a string you would not need the fpurge.
Presumably you want the account owner name to be more than a single character, but you're only reading a single character in that scanf. If you're trying to enter more than a single character there, the first scanf will read the first character, and since there's more in the input buffer, the next scanf will try to read immediately without waiting for your numeric input. If you are only using a single character for the owner name, then you'll need to consume the newline from the input buffer.
If you want to read a string as the account owner name, you'll need to allocate space for more than one character, and use %s rather than %c as your scanf format string. Also remember to check the return value for scanf. The function will return the number of items successfully scanned, or 0 if no items were scanned, typically due to invalid input, or return EOF.
char accountOwner[26];
// ...
// note that you can specify a width (max length) for a string using scanf
scanfReturn = scanf("%25s", accountOwner);
Hi all I am having a strange issue, when i use scanf to input data it repeats strings and saves them as one i am not sure why.
Please Help
/* Assment Label loop - Loops through the assment labels and inputs the percentage and the name for it. */
i = 0;
j = 0;
while (i < totalGradedItems)
{
scanf("%s%d", assLabel[i], &assPercent[i]);
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%s", assLabel[i]);
i++;
}
Input Data
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
Output Via Console
Prog1QuizQuizProg2MdtmMdtmFinal
Final diagnosis
You don't show your declarations...but you must be allocating just 5 characters for the strings:
When I adjust the enum MAX_ASSESSMENTLEN from 10 to 5 (see the code below) I get the output:
Prog1Quiz 20
Quiz 20
Prog2Mdtm 20
Mdtm 15
Final 25
You did not allow for the terminal null. And you didn't show us what was causing the bug! And the fact that you omitted newlines from the printout obscured the problem.
What's happening is that 'Prog1' is occupying all 5 bytes of the string you read in, and is writing a null at the 6th byte; then Quiz is being read in, starting at the sixth byte.
When printf() goes to read the string for 'Prog1', it stops at the first null, which is the one after the 'z' of 'Quiz', producing the output shown. Repeat for 'Prog2' and 'Mtdm'. If there was an entry after 'Final', it too would suffer. You are lucky that there are enough zero bytes around to prevent any monstrous overruns.
This is a basic buffer overflow (indeed, since the array is on the stack, it is a basic Stack Overflow); you are trying to squeeze 6 characters (Prog1 plus '\0') into a 5 byte space, and it simply does not work well.
Preliminary diagnosis
First, print newlines after your data.
Second, check that scanf() is not returning errors - it probably isn't, but neither you nor we can tell for sure.
Third, are you sure that the data file contains what you say? Plausibly, it contains a pair of 'Quiz' and a pair of 'Mtdm' lines.
Your variable j is unused, incidentally.
You would probably be better off having the input loop run until you are either out of space in the receiving arrays or you get a read failure. However, the code worked for me when dressed up slightly:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char assLabel[10][10];
int assPercent[10];
int i = 0;
int totalGradedItems = 5;
while (i < totalGradedItems)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
{
fprintf(stderr, "Error reading\n");
exit(1);
}
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
i++;
}
return 0;
}
For the quoted input data, the output results are:
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
I prefer this version, though:
#include <stdio.h>
enum { MAX_GRADES = 10 };
enum { MAX_ASSESSMENTLEN = 10 };
int main(void)
{
char assLabel[MAX_GRADES][MAX_ASSESSMENTLEN];
int assPercent[MAX_GRADES];
int i = 0;
int totalGradedItems;
for (i = 0; i < MAX_GRADES; i++)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
break;
}
totalGradedItems = i;
for (i = 0; i < totalGradedItems; i++)
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
return 0;
}
Of course, if I'd set up the scanf() format string 'properly' (meaning safely) so as to limit the length of the assessment names to fit into the space allocated, then the loop would stop reading on the second attempt:
...
char format[10];
...
snprintf(format, sizeof(format), "%%%ds%%d", MAX_ASSESSMENTLEN-1);
...
if (scanf(format, assLabel[i], &assPercent[i]) != 2)
With MAX_ASSESSMENTLEN at 5, the snprintf() generates the format string "%4s%d". The code compiled reads:
Prog 1
and stops. The '1' comes from the 5th character of 'Prog1'; the next assessment name is '20', and then the conversion of 'Quiz' into a number fails, causing the input loop to stop (because only one of two expected items was converted).
Despite the nuisance value, if you want to make your scanf() strings adjust to the size of the data variables it is reading into, you have to do something akin to what I did here - format the string using the correct size values.
i guess, you need to put a
scanf("%s%d", assLabel[i], &assPercent[i]);
space between %s and %d here.
And it is not saving as one. You need to put newline or atlease a space after %s on print to see difference.
add:
when i tried
#include <stdio.h>
int main (int argc, const char * argv[])
{
char a[1][2];
for(int i =0;i<3;i++)
scanf("%s",a[i]);
for(int i =0;i<3;i++)
printf("%s",a[i]);
return 0;
}
with inputs
123456
qwerty
sdfgh
output is:
12qwsdfghqwsdfghsdfgh
that proves that, the size of string array need to be bigger then decleared there.