I am new to C and I am trying to figure out how to create separate strings (char[]) made up of a mix of char[]s and ints that line up in length-
for example if I have char[] first name, char[] last name and int age I need them all on 1 line the same length example -
Joe |smith |45
Amy |Footh |2
with each line being its own char[] and lining up.
This is the code I have so far -
while(temp != NULL)
{
char listLine[IDLEN + FOODNAMELEN + DESCLEN + 10];
char * id = temp->data->id;
char * name = temp->data->name;
int dollars = temp->data->price.dollars;
int cents = temp->data->price.cents;
sprintf(listLine,"%s |%s |$%d.%d\n", id, name, dollars, cents);
printf("%s",listLine);
temp = temp->next;
}
This works OK but I cant seem to line up the | with each other.
Im still new to stack exchange, so I am not sure how to mark as homework... but yes this is homework.
any help would be great.
Thanks
You can use width specifiers with the printf format specifiers.
Example:
printf("%3d | %10s", 32, "Hello");
will print
_32 | _____Hello
where _(underscore) represents a space
You can also specify width as an argument using printf("%*d", width, 32);. The width can be determined by the length of strings you are printing. The maximum length of a string can be your desired width. For numbers you can assume no number (32-bit number) will be greater than 10 digits (232 has 10 digits in decimal notation)
See this
If you're trying to line these up on the pipe characters ('|'), then you could make a first pass on your data to determine the maximum length of each field in characters, and then on the second pass, space-pad each field that is shorter than it's maximum so that when all have been formatted, each field will be exactly the same length.
Or, you could determine the max length you want for each field and then format those using a printf() statement.
It sounds to me like you're wanting to add tabs? You can add tabs by adding \t
"%s \t|%s \t|$%d.%d\n"
Related
I am given a text file of movie showtime information. I have to format the information in a clean way. Right now I'm just trying to get all line's information saved into strings. However, when getting the movie's rating the array wont save the rating properly.
This is the main code.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const int MAX_TITLE_CHARS = 44; // Maximum length of movie titles
const int LINE_LIMIT = 100; // Maximum length of each line in the text file
char line[LINE_LIMIT];
char inputFileName[25];
FILE *file;
file = fopen("D:\\movies.txt", "r");
char currentLine[LINE_LIMIT];
char movieTitle[MAX_TITLE_CHARS];
char movieTime[10];
char movieRating[10];
fgets(currentLine, LINE_LIMIT, file); // Get first file
while(!feof(file)){
sscanf(currentLine, "%[^,],%44[^,],%s", movieTime, movieTitle, movieRating);
printf("%s\n", movieRating);
fgets(currentLine, LINE_LIMIT, file); // Get next file
}
return 0;
}
This is the CVS file
16:40,Wonders of the World,G
20:00,Wonders of the World,G
19:00,Journey to Space ,PG-13
12:45,Buffalo Bill And The Indians or Sitting Bull's History Lesson,PG
15:00,Buffalo Bill And The Indians or Sitting Bull's History Lesson,PG
19:30,Buffalo Bill And The Indians or Sitting Bull's History Lesson,PG
10:00,Adventure of Lewis and Clark,PG-13
14:30,Adventure of Lewis and Clark,PG-13
19:00,Halloween,R
This prints out
G
G
PG-13
PG-13
PG-13
PG-13
PG-13
PG-13
R
I need it to be
G
G
PG-13
PG
PG
PG
PG-13
PG-13
R
I use Eclipse and when in the debugger, I see that when it encounters the first PG-13, it doesn't update at all until the R. I'm thinking maybe since PG and PG-13 have the same two starting characters perhaps it gets confused? I'm not sure. Any help is appreciated.
You are converting the line using the following line:
sscanf(currentLine, "%[^,],%44[^,],%s", movieTime, movieTitle, movieRating);
the function will read a string into movietTime until a ',' appears in the input, then it will read another string until either a ',' appears or 44 characters are read. This behavior is explained in the manual for sscanf:
...
An optional decimal integer which specifies the maximum field width.
Reading of characters stops either when this maximum is reached or when
a nonmatching character is found, whichever happens first...
The lines with PG ratings have titles with 62 characters. Thus, it does not read the entire title, and does not find the comma. To fix this issue, you can either set MAX_TITLE_CHARS to a greater value or use the %m modifier to have sscanf dynamically allocate the string for you.
OP code had undefined behavior (UB) as the movieTitle[] was only big enough for 43 character + the terminating null character and OP used "%44[^,]" rather than the correct width limit of 43.
const int MAX_TITLE_CHARS = 44; // Maximum length of movie
...
char movieTitle[MAX_TITLE_CHARS];
Other problems too that followed this UB.
Account for the '\n' of the line and a '\0' to form a string.
Never use while(feof(...)).
Test sscanf() results.
Limit printed title width with a precision.
const int LINE_LIMIT = 100; // Maximum length of each line in the text file
char line[LINE_LIMIT + 2 /* room for \n and \0 */];
while (fgets(currentLine, sizeof currentLine, file)) {
// Either use a _width limit_ with `"%s"`, `"%[]"` or use a worse case size.
char movieTime[10 + 1]; // 10 characters + \0
char movieTitle[sizeof currentLine];
char movieRating[sizeof currentLine];
// Examples:
// Use a 10 width limit for the 11 char movieTime
// Others: use a worst case size.
if (sscanf(currentLine, " %10[^,], %[^,], %[^\n]",
movieTime, movieTitle, movieRating) != 3) {
fprintf(stderr, "Failed to parse <%s>\n", currentLine);
break;
}
// Maximum length of movie titles _to print_
const int MAX_TITLE_CHARS = 44;
printf("Title: %-.*s\n", MAX_TITLE_CHARS, movieTitle);
printf("Rating: %s\n", movieRating);
}
Note that "Maximum length of each line" is unclear if the length includes the ending '\n'. In the C library, a line includes the '\n'.
A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a
terminating new-line character is implementation-defined. C17dr § 7.21.2 2
Your string 'Buffalo Bill...' is more than 44 characters. thus the sccanf statement reads up to that limit, it then looks for a ',', which doesn't exist 44 characters into the string and exits.
Because your new movieRating isn't being set, it just prints the previous value.
Hint: If you are looking for a work around, you can parse your string with something like strsep(). You can also just increase the size of your movie title.
is there anyway to use scanf to scan a line of things which contain different types of data for example , string and float and int IN C (c99)?
Heres my code
{
float numberwithdot;
int number;
printf("Enter name: ");
scanf("%d,%f",&number,&numberwithdot);
printf("Your name is %d %f.",number,numberwithdot);
return 0;
}
after i run the program and enter the value (23 2.3), it process finished with exit code 0 but out put with (2 2.000000) ,which is not good.Anyway , wanted to know is it possible or not using scanf to do "that"
*******New*******
Sorry i may have post a idiot sample for the question , take a look at my "failure" code
{
int recordnumber ,itemnumber ,quantity ;
float weight ;
char itemname[30];
char category[30];
char namelocationstat[30];
printf("Please enter 1> Record number, 2> Item name, 3> Item number, 4> Category, 5> Quantity\n""6> Weight 7> Recipient-, 8> Final Destination-, and 9> Delivery status :\n");
scanf("%d,%s,%d,%s,%d,%f,%s",&recordnumber, itemname,&itemnumber, category,&quantity,&weight, namelocationstat);
printf("%d,%s,%d,%s,%d,%.1f,%s", recordnumber, itemname, itemnumber, category, quantity, weight, namelocationstat);
}
i was think to use strtok to define between names and adress(havent finish the code yet) , but that off the topic , The problem i got this (1,��,0,#,0,0.0,) after inputting (1 asd 2 sad 1 1.1 asdasd asd da)
hopefully u guys can solve it , it helps alot!!
***NEW****
Problem Solved , its because of the comma i added , how folish i am !!!
Sorry for your time everyone , You guys are so awesome , sacrificing time to help ppl like me !! Wish u all have a good day ! Sir or Madam!
P.S. new "programmer" alert
Anyway , wanted to know is it possible or not using scanf to do "that"
Yes, it is.
scanf continues processing the input as long as the input matches (i.e. can be turned into something matching) the format stream.
Since you match for:
scanf("%d,%f",&number,&numberwithdot);
^
comma
the input must contain an integer (%d) followed by a comma followed by a float (%f).
Since your input is 23 2.3 without a comma scanf can only match the first integer.
Had your input been 23,2.3 with a comma, your code would have worked.
An advice: Always check the value returned by scanf like:
if (scanf("%d,%f",&number,&numberwithdot) != 2)
{
// Error! Did not scan exactly 2 values
}
Is it possible to use scanf() to scan different type of data and store it (string and float and int)?
Yes, of course:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char str[21]; // Space for 20 characters + a terminating '\0'.
float f;
int i; // +------------------------------ % begins a conversion specification
// | +---------------------------- 20 specifies the with of the string to read
// | |+--------------------------- s conversion format specifier*)
// | || +------------------------- f conversion format specifier for float
// | || | +----------------------- i conversion format specifier for int
if (scanf("%20s%f%i", str, &f, &i) != 3) { // scanf() returns the number of
// arguments successfully assigned
fputs("Input error! Expected a string containing no whitespace, a float and an integer.\n\n", stderr);
return EXIT_FAILURE; // return an error code
}
printf("\"%s\"\n%f\n%i\n", str, f, i);
}
*) When using "%s" A L W A Y S specify the width of the string to read: "%[WIDTH]s", "%20s" in the example. The target (the array str in our example) must be at least of size width + 1.
It works just fine (just tested it). The problem is how you're imputing your numbers. Try this:
23,2.3
Furthermore, if you desire to input the way you tried, you need to change the string passed as argument to scanf:
scanf("(%d %f)",&number,&numberwithdot);
all,
I'm working on some of the challenges at CodinGame.com and I'm having some trouble with a challenge that requires me to display a letter in ASCII form using a loop of rows with "#"s and spaces where each "letter" is 3 characters long and 5 tall. For example:
Line 1 = " # "<br>
Line 2 = "# #"<br>
Line 3 = "###"<br>
Line 4 = "# #"<br>
Line 5 = "# #"<br>
Here is the relevant code for the program up to now:
int L; // Length of ASCII art char, always 3
scanf("%d", &L); // <- CodinGame scanf's all values from case into stdin
int H; // Height of ASCII art char, always 5
scanf("%d", &H); fgetc(stdin);
char T[257]; // <- Characters that must be turned into ASCII art
char lclcpy[1025]; // <- Copy array for me to use outside of loop.
fgets(T, 257, stdin); // <- T is drawn from case to stdin
for (int i = 0; i <= H; i++) {
char ROW[1025]; // <- String containing the current row of "#"s and spaces
strncpy(lclcpy, ROW, sizeof(lclcpy)); // <- I copy the row into my local copy.
fgets(ROW, 1025, stdin); // <- Program draws ROW into its stdin.
fprintf(stderr, "%s", lclcpy); // <- I print out the value of ROW on this line alone to debug. CodinGame uses stderr for debugging purposes.
}
Once the loop is complete, I end up with the alphabet in ASCII art, which is what my lclcpy looped through and printed.
What I want to do is copy only the segments of the big ASCII art image that correspond to a specific letter. I was able to do this in C++ because strings make life worth living, but I'm tearing my hair out trying to do this in C.
I figure I'd create an array of character pointers, with each element of the array pointing to the segments of ROW/lclcpy that contain a letter's data. Unfortunately, I've had no luck trying to do anything with character pointer arrays or two-dimensional character arrays. I keep getting segfaults and other memory problems. I'm not comfortably familiar with pointers yet. Seems I can only think in string mode, and nothing I've found has helped. Any help is greatly appreciated. Please consider my lack of experience. Thank you.
int n = argv[i][j];
n = n + (int)argv[1];
/* I'm pretty sure the above part that is wrong. What I was hoping that this
would do is take the number the person put in and increase n by that number but
it isnt working*/
printf("%d\n", n);
i = the string numbers of the argument
j = the characters of the string
What I want is to make it so when someone types ./123 12 hi I want it to increase the ascii characters of h and i by 12 or whatever number they put in. When I test my code out with
./123 1 hi
I get an output of
-1081510229
-1081510228
instead of
105
106
which is i and j, the next letters of h and i
Libraries I'm using
stdio.h
studio50.h
string.h
argv[1] is a string (i.e, a null-terminated char array), casting it to int doesn't give the result you expected
You should use atoi to do the job. Or better, use strtol to get better stability.
I am reading a book and I can't figure out this try it out : (it is in a non-english language so I translated it)
Write a program that ask for a number of students n, select n students (in a dynamic way), the name is 10 characters and note on 5 characters
Create a text file note.txt from the selection above and append hyphens to reach 10 characters (for the names).
Then read the file and from it (only), calculate the total. Then display the name and note of those that have a note that is not greater than 10.
You must implement 3 functions : createStudent, createFile and readFile, and not use global variables.
syntax : name must declared as char nom[10+1] (ie James, and then 5 hyphens will be added in order to get 10 characters) => james----- and note : char[5+1] (ie 15.00 or 07.50)
Tips : To convert the note from text format to float, you can use the atof function
I created the createStudent and createFile functions. they work well but I can't figure out the last part (readFile function).
My text file has this shape : Bart------ 04.50 Lisa------ 18.00 Homer----- 03.00
void readFile(int n){
FILE* file = NULL;
double temp= 0.0, average= 0.0;
double *total = (double*)malloc(n*sizeof(double));
int position = 0;
char information[5+1]="";
file = fopen("c:\\myFile.txt","r");
fseek(file,10,SEEK_SET);
while(fgetc(file) != EOF)
{
fscanf(file,"%5s",&information);
temp = atof(information);
total[position]= temp;
position++;
fflush(stdin);
fseek(file,11,SEEK_CUR);
}
fclose(file);
for(int compteur=0;compteur<2;compteur++)
{
moyenne += totalNote[compteur];
}
It compiles but doesn't work and I can't figure out why :(
I have the feeling that C language is such a pain in the ass compared to java or c#
Could you please give me some lights ?
It looks like your input file contains lines of the form " ". If there is always a fixed number of strings/numbers per line you can simply use fscanf (e.g. fscanf(file, "%*s %f %*s %f %*s %f", &number1, &number2, &number3);).
If, on the other hand, you can have an arbitrary number of string/number pairs per line, you should take a look at the strtok function.
You want to look into using strtok_r (or strtok if strtok_r not available). You can then convert your string into an array of token with space delimiter. Then it should be trivial to loop thur the array to convert and sum the amounts.
Use either fscanf or a combination of fgets,strtok,atol(or sscanf) to read the number.