About left padding in C programming? - c

I searched through the website already, but I can't seem to find the solution that pertains to my problem:
Example:
printf("%s I love puppies", name);
this is my prinf statement, but how do I left pad in which it will add additional spaces with each for loop?
Edit:
Hello //int i is 0
Hello //int i is 1
Hello //int i is 2
Hello //int i is 3
I wanted to do something like this:
(in for loop)
space += " " //where space is first initialized as ""
Is there a function that is similar to this (in java) in C programming?
Edit: The thing is I have this : printf("%s I love puppies", name);
I was thinking of using int space = i (according to the loop counter) and then do printf("%s", space, "%s I love puppies", name); in printf but it says I have too many arguments...

You can supply the %s format conversion with a length (just like any other format code). So %10s will print at least 10 characters.
By default, strings are padded on the left with spaces. (That's the same as other format codes, too.) You can't change the character that printf pads with, but you can get it to pad on the right by using a -: %-10s.
Length specifications can be replaced with a *, which will cause printf to use an int parameter prior to the parameter being converted, and use its value as the length. (You can do this with precision values as well.)
I imagine that what you are trying to do is a variable indent. Putting the above together, you can do it like this:
for (int indent = 0; indent < 20; ++indent) {
printf("%*s%s\n", indent, "", the_string);
}

Perhaps perform a printf(" "); in a loop that uses the existing loop count as a limiting factor something like:
for( i=0; i<namelimit; i++ )
{
for(j=0; j<i; j++ )
{
printf(" ");
}
printf("%s\n",name);
}

Related

Having issues on assigning a word to length

I'm trying to write a program that does the following:
Enter a word: supercalifragilisticoespialidoso
The word's length is: 32.
Enter a smaller number than the length: 23
The word cut on letter 23 is: supercalifragilisticoes.
For that I'm doing:
#include <stdio.h>
#include<string.h>
#define DIM 99
int main() {
char name[DIM], name2[DIM];
int length, length2;
printf("Enter a word: ");
scanf("%s", name);
length = strlen(name);
printf("The word's length is: %d\n", length);
printf("Enter a smaller number than the length: ");
scanf("%d", &length2);
name2 = name[length2];
printf("The word cut on the letter %d is: %c", length2, name2);
return 0;
}
But I get
main.c:16:11: error: assignment to expression with array type
The problem is in the line name2 = name[length2], that's the way I found to create the new smaller word, but it's not right.
Could someone please help?
The mistake is in the line
name2 = name[length2];
You're trying to assign a character (the one of index length2 inside name) to an array (name2).
What you actually want to do is this:
strncpy(name2, name, length2);
name2[length2] = '\0';
This copies the first length2 bytes of name into name2 and adds a terminating null character for safety (strncpy doesn't do it if all of the bytes are written).
If you don't intend to use name again, you could as well remove name2 altogether and add a null character to name:
name[length2] = '\0';
You're also printing a string with a %c format specifier on the last printf call. You should use %s instead.
Other answers have suggested how you might make a copy of the initial substring of your input or how to modify the input string in place. Those are perfectly good approaches, and both have plenty of uses in real-world programs.
However, if all your program needs to do is print the wanted substring then there is no need to do any string manipulation at all. printf can do the job by itself. Given the variables as you declared them and this code ...
scanf("%s", name);
length = strlen(name);
printf("The word's length is: %d\n", length);
printf("Enter a smaller number than the length: ");
scanf("%d", &length2);
... you can use a printf format to print name into a bounded-length field whose length is given by another printf argument:
printf("%.*s\n", length2, name);
That also adds a newline after, which is usually what one wants, but you can leave that off if you prefer.
The .* in the formatting directive indicates that a "precision" is being specified for the field via a printf argument. Other variations can express a fixed precision directly in the format. The significance of a precision depends somewhat on the directive type, but for s directives it is the maximum number of characters to be printed from the corresponding string argument.
There are two main errors in your code, and a couple of other minor points.
First, you can't directly assign arrays (be they character strings or any other array type) in C; for nul-terminated char arrays (strings), you can copy one to another using the strcpy function, or copy part of one to another using strncpy (which is what you want in your case).
Second, you can't print a string using the %c format specifier – you need %s for those.
And, a less serious issue (but one to avoid, if you want to be a good programmer) is that functions that work with string lengths (like strlen and strncpy) generally use size_t types, rather than int; and these require using the %zu format specifier, in place of %d.
Here's a version of your code that does what you want:
#include <stdio.h>
#include<string.h>
#define DIM 99
int main()
{
char name[DIM], name2[DIM] = { 0 }; // Fill with zeros to start, so we will have a nul terminator
size_t length, length2; // Strictly, use "size_t" for "strlen" and "strncpy"
printf("Enter a word: ");
scanf("%s", name);
length = strlen(name);
printf("The word's length is: %zu\n", length); // Use "%zu" for the "size_t" type
printf("Enter a smaller number than the length: ");
scanf("%zu", &length2); //Again, "%zu" for "size_t"
strncpy(name2, name, length2); // Use this function to copy a substring!
printf("The word cut on the letter %zu is: %s", length2, name2);// Note that you need "%s" to print a string
return 0;
}
There are some other 'safety measures' that you can add to your code, to prevent buffer overruns and other faults. One would be to limit the initial string input to at most DIM - 1 characters; this would be trivial if you had a hard-coded value of 99 in place of DIM, because then you could use a call like the following:
scanf("%98s", name); // Read at most 98 characters (leaving space for the nul-terminator)
However, the macro DIM cannot be used inside the quoted format string. Instead, you can write its value (minus 1) into a separate string and use that as the format argument to scanf; so, we replace our initial scanf call, like so:
// scanf("%s", name); // This has the potential to overrun the "name" array!
char fmt[8];
sprintf(fmt, "%%%ds", DIM - 1); // Write "%98s" into the "fmt" string ...
scanf(fmt, name); // ...and use that for the "scanf" format
(Note that some compilers will warn about not using a string literal for the format argument, and some programmers may not 'approve' of doing so; however, it is perfectly legal C and, IMHO, a valid use of the scanf function.)
The assignment:
name2 = name[length2];
does not have the semantics you appear to have assumed. Rather name2 is an array while name[length2] is a a single character at the index length2 of the array name.
In any event arrays are not first-class data types in C and you cannot assign one array to another (as it appears you were perhaps intending) let alone assigning a char for an array.
Here you might explicitly strncpy() to copy the sub-string, but in this case that is perhaps unnecessary. You can simply remove the name2 array and:
printf( "The word cut on the letter %d is: ", length2 ) ;
for( int i = 0; i < length && i < length2; i++ )
{
putchar( name[i] ) ;
}
If you truly need to store the sub-string rather then simply outputting it then:
int i = 0 ;
for( i = 0; i < length && i < length2; i++ )
{
name2[i] = name[i] ;
}
name2[i] = '\0' ;
Both have the advantage of behaving deterministically if length2 were less than zero or greater than length which you fail to check.
Using strncpy():
int len = (length2 < 0 || length2 > length) ?
length :
length2 ;
strncpy( name2, name, len ) ;
name2[len] = '\0' ;
Of course all those length checks are largely defeated by the lack of safety in acquiring name in the manner you have in the first instance. Consider using fgets() instead, or even getchar() in a loop.

Is it possible to make some loop which scans always one number and one string more than once? (Part of my homework)

so in my CS course we have to make a calculator which reads input and then calculates the result after the = sign has been read.
Input always consists of one number followed by operator.
I'm now struggling with the way of scanning the input. I want to use some loop which would always store it like:
scanf("%lf %s ", &in, c);
Note: the calculator goes one operation after other. Thus in example below the plus sign works only for 20 and 4, and only then the result takes the division sign and gets divided by 8. Then the new result gets negated by 'neg' string.
E.g.: Input: 20 + 4 / 8 neg =
Output: Result: -3
This is how I tried to solve it. My intention was to make the loop store each number into a new "box" of array, and then to store each string into the new "line" of char array. The 4 in op array is meant to set the max length of the string, because i know that the longest string that can occur is "sqrt".
I see that the '\n' in the condition of for is probably useless but can't figure out how to do it...
I'm thinking about using either for, or a while loop.
int main(){
double in[10];
char op[5][4];
for(int i=0; i<5;i++){
scanf("%lf %s ", &in[i], op[i][4]);
}
printf("%.3f %s", in[0], op[0][0]);
return 0;
}
//just a "skeleton" of the code. There's more to it, but here I submitted just the part that I'm struggling with.
For example if I run this code, I want to write a few numbers followed by operator into the input.
I expect it to print the first number and string (just to check whether the loop works).
But actually it does absolutely nothing and just gives me some large negative number as a return.
From the man page of scanf
int scanf(const char *format, ...);
as you can see first argument is of const char * type i.e you need to provide valid address.
With this
char op[5][4]; /* 5 char array, in each char array you can have 4 char's
* i.e op[row][0] to op[row][3]. There is no op[i][4]
*/
you can have
for(int i=0; i<5;i++){
scanf("%s",op[i]); /* op[i] itself address, so don't need & */
}
or
for(int i=0; i<5;i++){
for(int j=0; j<4; j++) {
scanf(" %c", &op[i][j]); /* storing char by char */
}
}
Also while printing here use %c as op[0][0] is of char type.
printf("%.3f %c", in[0], op[0][0]);
In a scanf format string, %s indicates you want to read a string, meaning it needs the address of where to put that string. You are passing op[i][4] for it, which is a char.

Extra Character Whenever I Print Out at An Output

I am trying to do a FLAMES program as an assignment and since I can't exactly post my whole code here, I will type in the part of the code that seems to be causing me errors since whenever I print out something, there are unexpected extra characters going with the output.
I used a similar code as this one:
int main(){
char chari[100], temp[100];
int i, c;
printf("Enter a name: \n");
scanf(" %[^\n]s", chari);
for (i=1; chari[i]!='\0'; i++)
{
printf("%i\n", i);
}
c = i;
for (i=0; i<c; i++)
{
printf("%i < %i\n", i, c);
temp[i] = chari[i];
}
printf("%s \n", temp);
return 0;
}
I've been tweaking the codes for hours now but I still can't seem to find the problem. I'm also counting the number of letters in the string so I can stop some part of my program later on.
Input: cool
Expected output: cool
Actual Output: cool(<-t
You forgot to copy the terminating null character.
After your first loop c = i; holds the index of the 0 byte.
In the second loop you run until i < c, i.e. you do not copy that 0 byte
Without terminating nul your string is as long as another random 0 byte is found in memory.
Within a function only static variables are initialized. Hence your temp array hold indetermined values and you cannot rely to get a 0 character where you need it.
You need to copy 1 more byte.

C - File management, unable to obtain desired output

I am working on my school assignment and I've come across my first major hurdle... I am unable to write to a file or even retrieve input using scanf and fgets.
Problem 1:
FILE *f1;
char date_trans[100][15];
f1 = fopen("test.txt", "w");
if (f1 == NULL)
printf("File could not be opened.\n");
else
printf("Enter details (sender, receiver, amount.)\n");
for(i = 0; i <= element; i++)
{
for(j = 0; j <= 20; j++)
fgets(date_trans[i][j], 15, stdin);
printf("%s", date_trans[i][j]);
}
fclose(f1);
This is a small snippet; with the above code I am unable to retrieve the input entered and print it out on display/to a file.
My intent is to have 100 strings and up to 15 characters each.
So say if I were to enter a date like 18/12/15 or like 18-12-15, or a word like "Daniel", the program stops abruptly for a few seconds after I press enter and then proceeds to display "Press any key...".
I also receive this error...
[Warning] ...\assignment\test.c:22: warning: passing arg 1 of `fgets' makes pointer from integer without a cast
which I really do not understand as the variable date_trans is a string/an 2d array of characters, not an integer, right?
Edit:
Problem 2:
for (j=0; j <= 50 || !feof(f1); j++); // f1 opened in 'r' mode.
{
fscanf(f1, "%s %d %s %d %s %f", date_trans[j], &accsend[j], accnames[j],
&accreceive[j], accnamer[j], &amount_trans[j]);
printf("%d %s %d %s %d %s %.2f\n", j+1, date_trans[j], accsend[j], accnames[j],
accreceive[j], accnamer[j], amount_trans[j]);
}
In the code above, I am trying to input data through the stream f1 with function fscanf, which was opened in read mode. However the output makes the program hang and I am also unable to type or do any actions within the program.
As well, please advise whether my usage of !feof is correct/appropriate.
Thanks for any help.
I see two problems with the code you show:
The warning you get, because date_trans[i][j] is a char, not a char *
Your inner loop goes from 0 to 20 (inclusive) and you use that as index into an array with 15 elements (i.e. indexes from 0 to 14 inclusive).
To solve both problems, don't have the inner loop, instead in the outer do
fgets(data_trans[i], sizeof data_trans[i], stdin);
Problem number 1 also exists in the printf call, where you pass a single char to a format that expects a char *.
Lastly a note about your requirement of strings containing 15 characters: Don't forget the null-terminator, and its need for a space in the array as well. That means you currently have place for 14 characters plus the terminator.
Change this
fgets(date_trans[i][j], 15, stdin);
printf("%s", date_trans[i][j]);
to
fgets(date_trans[i], 15, stdin);
printf("%s", date_trans[i]);
date_trans[i][j] is char type not char *. Also you don't need j for loop.

reading multiple variable types from single line in file C

Alright I've been at this all day and can't for the life of me get this down, maybe you chaps can help. I have a file that reads as follows
1301,105515018,"Boatswain","Michael R.",ABC, 123,="R01"
1301,103993269,"Castille","Michael Jr",ABC, 123,="R03"
1301,103993267,"Castille","Janice",ABC, 123,="R03"
1301,104727546,"Bonczek","Claude",ABC, 123,="R01"
1301,104731479,"Cruz","Akeem Mike",ABC, 123,="R01"
1301,105415888,"Digiacomo","Stephen",ABC, 123,="R02"
1301,106034479,"Annitto Grassis","Susan",ABC, 123,="R04"
1301,106034459,"Als","Christian",ABC, 123,="R01"
And here is my code...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME 15
#define MAX_SUBSEC 3
#define N 128
//void printArr(struct *students);
struct student{
int term;
int id;
char lastname[MAX_NAME];
char firstname[MAX_NAME];
char subjectname[MAX_SUBSEC];
int catalog;
char section[MAX_SUBSEC];
}students[10];
int main(){
int term;
int id;
char lastname[MAX_NAME];
char firstname[MAX_NAME];
char sub[MAX_SUBSEC];
int cat;
char sec[MAX_SUBSEC];
char fname[N];
FILE *inputf;
printf("Enter the name of the text file: ");
scanf("%123s",fname);
strcat(fname,".txt");
inputf = fopen(fname,"r");
if (inputf == NULL){
printf("I couldn't open the file for reading.\n");
exit(0);
}
//TROUBLE HERE!
fscanf(inputf, "%d,%d,%[^,]s", &students[0].term, &students[0].id,students[0].lastname);
printf("%d\n", students[0].term);
printf("%d\n", students[0].id);
printf("%s\n", students[0].lastname);
/*for (j = 1 ; j <= 10-1 ; j++){
for(k = 0 ; k <= 10-2 ; k++){
if(students[k] > students[k+1]){
temp = students[k];
students[k] = students[k+1];
students[k+1] = temp;
}
}
}*/
fclose(inputf);
system("pause");
return 0;
}
void printArr(int a[], int tally){
int i;
for(i = 0 ; i < tally ; i++){
printf("%d ", a[i]);
}
printf("\n");
}
My objective is to take each one of those values in the text file and input it to where it belongs in the struct and subsequently the struct array, but I can't get passed the first 2 ints.
Getting the lastname string, because it is a max of 15 characters, it spills over into the first name string right after it and takes what remaining characters it needs in order to fill up the lastname char array. Obviously I do not want this. As you can see I have tried strtok but it doesnt do anything, not sure what I have to do though as I have never used it before. Also have tried just including all the variables into fscanf statement, but I either get the same output, or it becomes a mess. As it is, I am extremely lost, how do I get these values into the variables they belong?!
EDIT: updated my code, I have gotten a little farther but not much. I can now print out just the last name but can not more farther from there, I cant get to the firstname string or any of the variables beyond it.
What you have there is a CSV file with quoted strings, and so I would recommend you use a CSV parser (or roll your own) rather than trying to do it all with scanf (since scanf cannot deal with quotes, e.g. commas within quoted strings). A quick Google search turns up libcsv.c which you may be able to use in your project.
With the fscanf format string "%d,%d,\"%[^\"]\",\"%[^\"]\",%[^,],%d,=\"%[^\"]\"" we can read a whole line's data. Besides, you have to define
char lastname[MAX_NAME+1];
char firstname[MAX_NAME+1];
char subjectname[MAX_SUBSEC+1];
int catalog;
char section[MAX_SUBSEC+1];
— the +1 to account for the terminating '\0' character.
I have a question for you... If you want to know how to use a diamond cutter, do you try it and see, or do you consult the manual? The problem here isn't the result of your choice, but your choice itself. Believe it or not, I have answered these questions so often that I'm tired of repeating myself. The answer is all in the manual.
Read the POSIX 2004 scanf manual — or the POSIX 2008/2013 version — and the answer this question and you'll have some idea of what you're not doing that you should be. Even fscanf code should use assert as a debugging aid to ensure the number of items read was correct.
%[^,]s It seems as though there's a mistake here. Perhaps you meant %[^,]. The %[ format specifier is a different format specifier to the %s format specifier, hence in the presumably mistaken code there are two directives: %[^,] and s. The s directive tells scanf to read an 's' and discard it.
1.There is a syntax error in
while(result != NULL){
printf(".....);
......
}
}//error
fscanf(inputf, "%s", lastname); can't read a line ,fscanf will stop when it comes across an space
fscanf reads one line at a time, and you can easily capture the contents of each line because your file is formatted pretty nicely, especially due to the comma separation (really useful if none of your separated values contain a comma).
You can pass fscanf a format like you're doing with "%d" to capture an int, "%s" to capture a string (ends at white space, be weary of this when for example trying to find a name like "Annitto Grassis, which would require 2 %s's), etc, from the currently read line of the file. You can be more advanced and use regex patterns to define the contents you want captured as chars, such as "Boatswain", a sequence comprised chars from the sets {A-Z}, {a-z}, and the {"}. You'll want to scan the file until you reach the end (signified by EOF in C) so you can do such and capture the contents of the line and appropriately assign the values to variables like so:
while( fscanf(inputf, "%d,%d,%[\"A-Za-z ],%[\"A-Za-z .]", &term, &id, lastname, firstname) != EOF) {
.... //do something with term, id, lastname, firstname - put them in a student struct
}
For more about regex, Mastering Regex by Jeff Friedl is a good book for learning about the topic.

Resources