I have a need to print a variable number of a given character in conjunction with my formatted output. I was looking for something similar or equivalent to the VBA function String(num, char), but haven't been able to find any. I've written a function to do the job but if there is something built-in that does it I'd love to know. Here's what I have. For the purpose of testing I'm using a sloppy implementation of argv[].
What I want to is print out something like this;
Here's the rough implementation I've come up with;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char * make_string(int num, char character)
{
char *strchars = malloc(num);
for (int i = 0; i < num; i++)
strchars[i] = character;
return strchars;
}
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; i++) {
printf("%s\n", make_string(strlen(argv[i]),'_'));
printf("%s%c %s\n", make_string(strlen(argv[i]),'_'),'|', argv[i]);
}
}
Is there a library function for printing strings of repeating characters like this?
Credit for this answer goes to UmamaheshP for pointing me in the right direction with a comment. This is what I was looking for and was adapted from an example he linked to.
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
int i;
char *pad = "________________";
for (i = 1; i < argc; i++)
printf ("%.*s\n%.*s%c %s\n", strlen(argv[i]),
pad,strlen(argv[i]), pad, '|', argv[i]);
}
Related
I am trying to write a program that takes first names and last names from stdin separated by newline and stores them in char arrays inside of a struct array. Everything seems to be working fine until I want to print them in a certain way. I need the names to be formatted like this on the output:
<lastName>, <firstName> That is why I added a function to remove the trailing newline from the end of each line when parsing the values. It however does not return anything when doing this:
printf("%s, %s",people[0].lastName, people[0].firstName);
However when printing the values on seperate lines like
printf("%s\n",people[0].lastName);
printf("%s\n",people[0].firstName);
or using puts
puts(people[0].lastName);
it works just fine.
When I comment out the removeNewline() function it seems to get rid of the problem. But with the newline at the end I cannot format the output the way I desribed.
Here is my full code:
#include <stdio.h>
#include <string.h>
#define MAX_STRING_LENGTH 100
#define MAX_PEOPLE 42
struct Person{
char firstName [MAX_STRING_LENGTH];
char lastName[MAX_STRING_LENGTH];
};
void removeNewline(char * string){
for(int i = 0; string[i] != '\0'; i++){
if(string[i] == '\n'){
string[i] = '\0';
}
}
}
int parseData(struct Person * people){
int peopleCounter;
for(peopleCounter = 0; peopleCounter < MAX_PEOPLE; peopleCounter++){
char firstName[MAX_STRING_LENGTH];
char lastName[MAX_STRING_LENGTH];
if(fgets(firstName,MAX_STRING_LENGTH,stdin) == NULL){
break;
}
fgets(lastName,MAX_STRING_LENGTH,stdin);
removeNewline(firstName);
removeNewline(lastName);
strcpy(people[peopleCounter].firstName,firstName);
strcpy(people[peopleCounter].lastName,lastName);
}
return peopleCounter;
}
int main(int argc, char *argv[]){
struct Person people [MAX_PEOPLE];
parseData(people);
//PROBLEM
printf("%s, %s",people[0].firstName, people[0].lastName);
for(int i = 0; i < 2; i++){
printperson(people, i);
}
}
I am giving the values from a text file through redirection like so:
./main <people.txt
people.txt example:
George
Washington
Thomas
Jefferson
desired output:
Washington, George
Jefferson, Thomas
I am not able to reproduce the issue. Here are the minor changes:
removeNewline(): return after we process the first newline. Streamlined it a bit.
parseData(): store directly in struct instead of temporary variables. Renamed peopleCounter to i as it was it unnecessary long. Check return value of 2nd fgets(), too.
main(): Removed call to printperson() and looped over the returned values with the two arguments variables switched in the printf() statement for the expected order.
#include <stdio.h>
#include <string.h>
#define MAX_STRING_LENGTH 100
#define MAX_PEOPLE 42
struct Person{
char firstName[MAX_STRING_LENGTH];
char lastName[MAX_STRING_LENGTH];
};
void removeNewline(char *s) {
for(;;) {
*s *= (*s != '\n');
if(!*s++) return;
}
}
int parseData(struct Person *people){
int i = 0;
for(; i < MAX_PEOPLE; i++){
if(!fgets((people + i)->firstName,MAX_STRING_LENGTH,stdin))
break;
removeNewline((people + i)->firstName);
if(!fgets((people + i)->lastName,MAX_STRING_LENGTH,stdin))
break;
removeNewline((people + i)->lastName);
}
return i;
}
int main(int argc, char *argv[]) {
struct Person people[MAX_PEOPLE];
int n = parseData(people);
for(int i = 0; i < n; i++) {
printf("%s, %s\n", people[i].lastName, people[i].firstName);
}
}
and the output is:
Washington, George
Jefferson, Thomas
I am supposed to create an array with the fixed size (let’s say 5x5). I am supposed to fill it with words typed as command line parameters. I can use only pointers. Obviously I have to create two dimensional array[5][5]. I can’t use more than 25 letters ( I will make if statements ). I am going replace white space with some symbol ($ or something). The problem is I don’t know how to connect those command line parameters with array using only pointers.
You need to use the argc and argv arguments from the main function.
Here is an example.
#include <stdio.h>
int main(int argc, char *argv[])
{
for (unsigned i = 1; i < argc; i++)
{
printf("Word %u is: %s\n", i, argv[i]);
}
return 0;
}
You compile it using gcc main.c -o a.exe.
And run it using a.exe hello world.
Edit:
Further to your comment.
You can create an array of pointers like so:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *my_array_of_strings[5]; // up to 5 strings
// populate your array
for (unsigned i = 1; i < argc; i++)
{
my_array_of_strings[i - 1] = malloc(strlen(argv[i]) + 1);
if (NULL == my_array_of_strings[i - 1])
{
printf("oh no, memory failure");
break;
}
memcpy(my_array_of_strings[i - 1], argv[i], strlen(argv[i]) + 1);
printf("word is %s\n", my_array_of_strings[i - 1]);
}
return 0;
}
I am trying to run below program in an online C compiler. But I get segmentation error. Can you help me fix this
#include <stdio.h>
#include <string.h>
int main()
{
char string[15] = "Strlwr in C";
printf("%s",tolower(string));
return 0;
}
Following is the prototype of tolower
int tolower(int c);
You should pass an int or something like char which can safely convert to int. Passing char * (Type of string) like you do leads to UB.
To convert a string to lowercase, you need to convert each character separately. One way to do this is:
char string[15] = "Strlwr in C";
char lstr[15];
int i = 0;
do {
lstr[i] = tolower(string[i]);
} while(lstr[i] != '\0');
printf("%s", lstr);
You are using tolower incorrectly. This function returns int and gets int as a parameter (here is it's declaration: int tolower(int c);). What you want to do is call it on each char of your char array, and print each one:
char string[15] = "Strlwr in C";
for(int i = 0; i < strlen(string); i++)
printf("%c",tolower(string[i]));
Read cplusplus.com/reference/cctype/tolower It takes a single int as parameter, not char and not array.
You probably want to use a loop on "string", which processes each in turn.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
int i;
char string[15] = "Strlwr in C";
for (i=0; i< sizeof(string)/sizeof(char); i++)
{
string[i]=(char)(tolower((int)string[i]));
}
printf("%s\n",string);
return 0;
}
Output:
strlwr in c
I am trying to write a small function to trim left spaces from a string, but I cannot get it right. In this version, I get the following error:
bus error: 10
Could anyone please explain to me what I am doing wrong? I am not looking so much for an alternative piece of code, but would like to understand the errors in my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void trim_string(char *);
int main(int argc, char *argv[]) {
char *temp = " I struggle with strings in C.\n";
trim_string(temp);
printf("%s", temp);
return 0;
}
void trim_string(char *string) {
char *string_trimmed = "";
int i=0, j=0;
while (isblank(string[i])) {
i++;
}
while (string[i] != '\0') {
string_trimmed[j] = string[i];
i++;
j++;
}
string_trimmed[j] = '\0';
strcpy(string, string_trimmed);
}
I have now found a workaround solution, shown below. But I am still not very clear about what I did wrong in the first place:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LENGTH 100
void trim_string(char [MAX_LENGTH]);
int main(int argc, char *argv[]) {
char temp[MAX_LENGTH] = " I struggle with strings in C.\n";
trim_string(temp);
printf("%s", temp);
return 0;
}
void trim_string(char string[MAX_LENGTH]) {
char string_trimmed[MAX_LENGTH];
int i=0, j=0;
while (isblank(string[i])) {
i++;
}
while (string[i] != '\0') {
string_trimmed[j] = string[i];
i++;
j++;
}
string_trimmed[j] = '\0';
printf("c\n");
strcpy(string, string_trimmed);
}
Both string and string_trimmed point to string literals, here in main:
char *temp = " I struggle with strings in C.\n";
^
|
This is a string literal
temp points to a string literal and the standard says you are not allowed to modify them.
In the function trim_string you are modifying a them which is undefined behavior of which a bus error is one possible result, although anything can happen.
string_trimmed either needs to be an array like this:
char string_trimmed[n] ;
where n is the size of your input using strlen(string) would probably make sense or dynamically allocated via malloc which you would need to free at the end of your function. The same things goes for your input from main, this would work as a substitute:
char temp[] = " I struggle with strings in C.\n";
For completeness sake, the draft C99 standard section 6.4.5 String literals paragraph 6 says (emphasis mine):
It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. If the program attempts to modify such an array, the behavior is
undefined.
I don't think I properly understand how to allocate memory for what I want to do.
I would like my program to store arguments from the command line into an array of stucts called Command which has char **args in it. for example if I run
./test.c echo hello : ls -l
I want it to store it as this
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[1].args[0]= ls
commands[1].args[1]= -l
But instead my code is storing it in this way
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[0].args[2]= ls
commands[0].args[3]= -l
commands[1].args[0]= ls
commands[1].args[1]= -l
Could someone help me understand why it is storing ls -l in 2 places? Here is my code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct test {
char **args;
} Command;
int main(int argc, char *argv[])
{
int i, j, k;
Command *commands;
j = k = 0;
commands = (Command *)malloc(argc * sizeof(Command));
for (i = 1; i < argc; i++)
{
if (strcmp(argv[i], ":") == 0)
{
j++;
k = 0;
}
else {
commands[j].args = (char **)realloc(commands[j].args, (k+1) * sizeof(char*));
commands[j].args[k++] = argv[i];
}
}
for (i = 0; i <= j; i++)
{
for (k = 0; k < 5; k++)
{
printf("commands[%d].args[%d]= %s\n", i, k, commands[i].args[k]);
}
}
return EXIT_SUCCESS;
}
Your data storage structure has no way of telling how many strings in commands[j] are valid. So I think it's putting two pointers each in commands[0] and commands[1] just like you expect. But then your print loop looks at commands[0].args[k] for k all the way up to 4, even though it's only valid to look at the first two. When you get up to looking at commands[0].args[2], the result is undefined. (Showing memory from somewhere else in your program, crashing, and catching fire are just a few of the things a program is allowed to do if you use undefined behavior.)
To figure out how many arguments are in each command, you could add a counter member to your struct test. Or maybe allocate one more pointer than there are arguments, and put a NULL after the last argument.
Here is how I would allocate the memory:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct cmd_s {
int num;
char **args;
} cmd_t;
void print_cmds(cmd_t *c, int num) {
int i, j;
for (i=0;i<=num;i++) {
for (j=0;j<c[i].num;j++)
printf("cmds[%d][%d] = %s\n", i, j,c[i].args[j]);
}
}
int main(int argc, char *argv[]) {
int i, j = 0, k = 0;
cmd_t *cmds;
cmds = (cmd_t *)malloc(sizeof(cmd_t));
cmds[0].args = NULL;
cmds[0].num = 0;
for (i=1;i<argc;i++) {
if (strcmp(argv[i], ":") == 0) {
cmds = (cmd_t *)realloc(cmds, (sizeof(cmd_t) * ++j) + 1);
cmds[j].args = NULL;
cmds[j].num = 0;
continue;
}
cmds[j].args = (char **)realloc(cmds[j].args, sizeof(char *) * ++cmds[j].num);
cmds[j].args[cmds[j].num-1] = (char *)malloc(50);
strcpy(cmds[j].args[cmds[j].num-1], argv[i]);
}
print_cmds(cmds, j);
for (i=0;i<=j;i++) {
for(k=0;k<cmds[i].num;k++)
free(cmds[i].args[k]);
free(cmds[i].args);
}
free(cmds);
return 0;
}
Each of your Command structs only have one arg
Perhaps you should consider
typedef struct test {
char **args[5];
} Command;
and then design a better data structure, like a list of lists.
Perhaps you should store the length of args in the struct?
typedef struct test {
char ** args;
unsigned length;
} Command;
Also, maybe you should consider using some of the built in functionality of the C string library. For example, strtok splits a string using the delimiters you give it.