Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I would like to write a program that will open a csv file and create its visualization in a txt file.
I mean:
input:
(this is csv file)
apple;orange;strawberry
car;warsaw;ansi
output in txt file
apple|orange|strawberry
car |warsaw| ansi
The idea is that the width of the whole column should be adjusted to the longest expression in it
output in my program
apple|orange|strawberry
|car|warsaw|ansi
|
I have too many separators, and they're not in line
My code:
#include <stdio.h>
#include <string.h>
#include <string.h>
#define MAXLINE 1000
int how_many_delimiter(char array[]);
int main(void)
{
FILE *f,*f_2;
int *size_of_column, counter, hmd, min;
char corrector[] = ";", rows[MAXLINE], *clipboard;
f = fopen("ex-5.csv", "r");
f_2 = fopen("wynik.txt", "w");
fgets(rows, MAXLINE, f);
hmd = how_many_delimiter(rows);
size_of_column = (int*)calloc(hmd,sizeof(int));
min=10;
while(fgets(rows, MAXLINE, f))
{
clipboard = strtok(rows, corrector);
counter=0;
if(strlen(clipboard)>size_of_column[counter])
{
size_of_column[counter] = strlen(clipboard);
}
while(clipboard!=NULL)
{
if(strlen(clipboard)>size_of_column[counter])
{
size_of_column[counter] = strlen(clipboard);
}
clipboard = strtok(NULL,corrector);
counter++;
}
}
fclose(f);
f = fopen("ex-5.csv", "r");
while(fgets(rows, MAXLINE, f))
{
clipboard = strtok(rows, corrector);
counter=0;
while(clipboard!=NULL)
{
fprintf(f_2,"%-*s|",size_of_column[counter], clipboard);
clipboard = strtok(NULL,corrector);
counter++;
}
}
fclose(f);
fclose(f_2);
return 0;
}
int how_many_delimiter(char array[])
{
int counter, i;
i = 0;
counter = 1;
while(array[i]!='\n'&& array[i]!=EOF)
{
if(array[i]==';') counter++;
i++;
}
return counter;
}
Steps to do this (using an alternate to the "%*s", width method):
Loop to get length of longest word in all categories
int len = strlen(longestWord);
Create format string container char formatStr[80];
Populate formatStr: sprintf(formatStr, "%s%d%s", "%", len+5, "s");
+5 is arbitrary, change as needed for space between columns.
Use formatStr in the printf() statements for each word.
So for example the longest word shown in your example is strawberry. My suggestion was to programmatically parse all of the words into buffers, and loop on them, performing strlen() on each to determine longest. Once you've found, in this case, strawberry, len will be 10, so the format specifier would be "%15s" (if you use my recommended +5). But the value 15 will be in an int variable by then (say for example int longest. Since inserting it directly into the normal format string: ( "%longests" ) will not compile, it will need to be packaged up into a format string, formatStr as shown in bullets above, and here:
sprintf(formatStr, "%s%d%s", "%", longest + 5, "s|");
( Will look like: "%s15s|" )
Once this is done, you can use the format string in the printf statements
This then:
fprintf(f_2,"%-*s|",size_of_column[counter], clipboard);
Becomes:
fprintf(f_2,formatStr, clipboard);
(either method will work.)
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Hi I have a text file from whitch i read row by row and paste result into a new file only a portion of string contained between character ! and character $
example:
origin:
Beautifull!day today$
!hello world$is nice
final:
day today
hello world
I have used in past this code and it was working now the output is an empty file.
#include <stdio.h>
#include <alloc.h>
#include <string.h>
FILE *string;
FILE *stringtxt;
int line = 0;
int i = 0;
int j;
char search = 33;
char search2 = 36;
int main(void)
{
stringtxt = fopen("C:\\Users\\Pc\\Desktop\\ups.m3u","a+");
if ((string = fopen("C:\\Users\\Pc\\Desktop\\ups.txt","a+")) == 0)
printf ("ERRORE");
else{
char input[512];
while (fgets(input,512,string)){
line++;
i = strlen(input);
for(j=0;j<i;j++){
if(input[j]==search){
input[j-0] = 0;
}
}
for(j=0;j<i;j++){
if(input[j]==search2){
memmove(input,input + j + 1, strlen(input));
printf("%s\n",input);
fprintf(stringtxt,"%s\n",input);
}
}
}
}
fclose(stringtxt);
}
You have various little errors in your code which prevent your program to do what you want.
As you read from one file and write to the other from the beginning you should use "r" mode to read and "w" mode to write. That would fix the problem that "a" sets the file pointer at the end of file and only allow it to grow.
Then if you want to extract the part starting at search and ending at search2 you should swap the variables.
With those minimal fixes it will become:
...
stringtxt = fopen("C:\\Users\\Pc\\Desktop\\ups.m3u","w"); // change 1
if ((string = fopen("C:\\Users\\Pc\\Desktop\\ups.txt","r")) == 0) //change 2
printf ("ERRORE");
else{
char input[512];
while (fgets(input,512,string)){
line++;
i = strlen(input);
for(j=0;j<i;j++){
if(input[j]==search2){ // change 3
input[j-0] = 0;
}
}
for(j=0;j<i;j++){
if(input[j]==search){ // change 4
memmove(input,input + j + 1, strlen(input));
printf("%s\n",input);
fprintf(stringtxt,"%s\n",input);
}
...
Above code also cleaned indentation and produces the expected result.
From your response to my comment, it seems like you would be satisfied with:
#include <stdio.h>
int
main(void)
{
int c;
int p = 0;
while( ( c = getchar()) != EOF ) {
switch(c){
case '\n': putchar(c); /* fallthru */
case '$': p=0;
}
if( p ){
putchar(c);
}
if( c == '!' ){
p = 1;
}
}
}
With problems like this, it is often not necessary to actually read full lines, and it is much simpler if you do not. This solution will print the data between the first ! and the first $. If you want to match on the inner pair, or the outer pair, it becomes necessary to read more than one character.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I'm attempting to write a program in which there is an integer, called numwords, that specifies the number of words read from a file. However, I am testing it against a file that has fewer words than what the user inputs. For instance, I have the input
this
should
not
work
in which numwords is 5 based on user input. I want to terminate the program with an exit code of 1, so I have written the following code to help me:
When I use files that have the appropriate number of words as the user inputs into numwords, not output appears to be printed out (the program has other functions that use wptrs to print values). Output was being printed before I added the while statement to my code. I feel that there is something wrong with my scanf statement in the while loop. Before I added to the while loop, I had used just the for loop and the commented-out scanf("%s", unused), and my program was working normally - input was being read in, and the appropriate output was used. I am just trying to implement a condition in which the above case with fewer words than numwords would fail, however.
//A huge chunk of memory that stores the null-terminated words contiguously
char chunk[MEMSIZE];
//Location of unused memory
char *unused = chunk;
//Points to words that reside inside of chunk
char *wptrs[MAX_WORDS];
/** Total number of words in the dictionary */
int numwords;
void readwords()
{
int i = 0;
while ((scanf("%s", unused)) != EOF) {
for (i = 0; i < numwords; i++) {
//Read in words and store them in chunk array
//scanf("%s", unused);
wptrs[i] = unused;
unused += mystrlen(wptrs[i]) + 1;
}
}
//Check to see if fewer input than specified
if (numwords > i) {
printf("%d", i);
exit(EXIT_NUM_WORDS_BAD);
}
}
I want this case to exit the program with an exit code of 1, but I find that it exits with a code of 0, as the main method just has return 0. Is there a way to exit with a code 1, and make my program work appropriately when there is an appropriate number of words that is equivalent to numwords? Thank you in advance.
Revised example: breaks out of the while loop if the word quota is met or if EOF is read.
I've arbitrarily chosen 5 for words_expected (rather, numwords in the original code). Once five lines of input are read, the results will be printed. No explicit EOF is required. If EOF is met before 5 words, the error is printed and we exit with return code 1.
Per your comment, I added a check for whether a given line contains only digits. If it does, the program will cease to process the input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MEMSIZE 1024
#define MAX_WORDS 5
//A huge chunk of memory that stores the null-terminated words contiguously
char chunk[MEMSIZE];
//Location of unused memory
char *unused = chunk;
//Points to words that reside inside of chunk
char *wptrs[MAX_WORDS];
/** Total number of words in the dictionary */
int words_expected = 5;
int contains_only_digits(char *s)
{
int i = 0;
for (i = 0; i < strlen(s); i++) {
if (!isdigit(s[i])) {
return 0;
}
}
return 1;
}
void readwords()
{
int words_read = 0;
while (words_read < words_expected && scanf("%s", unused) != EOF) {
// Read in words and store them in chunk array
wptrs[words_read] = unused;
if (contains_only_digits(wptrs[words_read])) {
break;
}
unused += strlen(wptrs[words_read]) + 1;
words_read++;
}
//Check to see if fewer input than specified
if (words_read < words_expected) {
printf("Expected %d words, but %d were provided\n", words_expected,
words_read);
exit(1);
}
}
void printwords()
{
int i = 0;
for (i = 0; i < words_expected; i++) {
printf("word %d: %s\n", i + 1, wptrs[i]);
}
}
int main(int argc, char **argv)
{
readwords();
printwords();
}
The contains_only_digits function is a naive implementation. It may be wise to use strtol and check errno if you are interested in best practices for determining whether a C string is a number.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I have to print formatted table of csv file. I wonder if you know about any specific library or a tool that can help me with this - I just didn't find anything by googling.
this is the code and the code works fine, just have to print it like a formatted table. thanks!
void opportunity_table()
{
int i = 3;
char line[LINESIZE];
FILE* fp = fopen("opportunity_table.csv", "r");
if (!fp) {
printf("File failed to open!\n");
exit(1);
}
while (fgets(line, LINESIZE, fp)) {
while (line[i] != '\n') {
if (line[i] == ',') {
printf("%s ", "");
}
else
printf("%c", line[i]);
i++;
}
i = 0;
puts(" ");
}
}
the input I get from running this code is messy and look really bad.
Make use of the width and precision fields of the %s specifier. The width field sets a width of at least the specified characters. The precision field will print up to the specified number of characters. Works as long as width is greater than precision.
strpbrk will give a pointer to the next character in the string or NULL.
The format string "%*.*s" will right justify the printing. Use "%-*.*s" to left justify.
#include <stdio.h>
#include <string.h>
#define WIDTH 7
int main( void) {
char csv[] = "a,b,cde,fghij,i,jh\n";
char *item = csv;
char *comma = NULL;
while ( *item && ( comma = strpbrk ( item, ",\n"))) {//pointer to each comma and the newline
printf ( "%*.*s", WIDTH, comma - item, item);
item = comma + 1;//skip the comma or newline
}
printf ( "\n");
return 0;
}
If the width of the fields needs to vary, an array of widths could be used.
#include <stdio.h>
#include <string.h>
int main( void) {
char csv[4][50] = {
"a,b,cde,fghij,i,jh\n",
"i,jk,lmno,pq,rst,uvw\n",
"0,1,2,3456,78,9\n",
"x,y,z,01,2345,6789\n"
};
char *item = NULL;
char *comma = NULL;
int width[] = { 3, 4, 6, 7, 6, 5};
int field = 0;
for ( int loop = 0; loop < 4; ++loop) {
field = 0;
item = csv[loop];
while ( *item && ( comma = strpbrk ( item, ",\n"))) {//pointer to each comma and the newline
printf ( "%*.*s", width[field], comma - item, item);
item = comma + 1;//skip the comma or newline
field++;
}
printf ( "\n");
}
return 0;
}
This could be customized by reading the file twice. The number of fields and the maximum width could be determined in the first read. Read the file the second time and print using the calculated widths.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am writing a C program to generate userid's from a given file (users). The file has each user's first and last names each line (eg. "John Smith", "Steve Mathews" etc). The following while loop reads each line from users and prints in the console in all lowercase. In this case, single_line holds names in lower case.
while(!feof(fp)) {
fgets(single_line, 80, fp);
for(int i = 0; single_line[i]; i++){
single_line[i] = tolower(single_line[i]);
}
char f_letter = single_line[0];
char r_letters[20];
}
Now, I want to create a username for each single_line with the first letter of the first name and remaining letters of last name. So far, f_letter holds the first letter of first name, how can I make r_letters hold the remaining letters of last name?
char first_name[81];
char last_name[81];
char user_name[82];
while(!feof(fp)) {
if(fscanf(fp, "%80s %80s", first_name,last_name) == 2){
for(i = 0; i < strlen(first_name); i++){
first_name[i] = tolower(first_name[i]);
}
for(i = 0; i < strlen(last_name); i++){
last_name[i] = tolower(last_name[i]);
}
sprintf(user_name, "%c%s", first_name[0], last_name);
}
}
You can use strtok to extract tokens from strings using a delimiter.
For example, for a line of text read from a file using fgets (assuming each line only contains two words, as is your case), you can extract the first and second words as:
char *first_name = strtok(single_line, " ");
char *last_name = strtok(NULL, "\n");
newline character is used as the second delimiter because fgets preserves it when reading a line, so it can be used to extract the last token before the newline.
Consider the following function for creating usernames:
#include <stdio.h>
#include <string.h>
void create_usernames(char *filename) {
char line[80], username[80];
char *last;
FILE *fp = fopen(filename, "r");
// fgets returns a NULL pointer upon EOF or error
while (fgets(line, 80, fp) != NULL) {
last = strtok(line, " ");
last = strtok(NULL, "\n");
printf("%c%s\n", line[0], last);
}
fclose(fp);
}
For example, with a file file.txt containing names:
John Smith
John Diggle
Bruce Wayne
Steve Mathews
you would have:
create_usernames("file.txt");
JSmith
JDiggle
BWayne
SMathews
find the index of the space between the first and last name, say j. the index of the first letter of the last name would be j+1.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
How can I read multiple lines (approximately 5000 lines) from a text file and store all of them in a single string array?
i already have some of the code running smooth, but it doesn't work the way its supposed to. I only get the last line of the file stored in the array.
int main(){
int n;
char line[401];
char string[10000];
fr = fopen ("fila1b.txt", "rt");
while(fgets(line, 400, fr) != NULL){
strcat(string, line);
}
fclose(fr);
printf("%s\n", string );
}
EDIT: I updated the code with some changes. Now i'm using the strcat function to insert the contents of the line got by fgets to the original string array. It is working, apparently. But when i print the 'string', it only prints the first 300 lines and then it gives me Segmentation fault.
The usual way is to just slurp all the characters with read or fread:
#define MIN_CHUNK_SIZE (1024)
char *read_file(FILE *f) {
size_t n_read_total = 0;
size_t buf_size = MIN_CHUNK_SIZE + 1; // Allow space for nul terminator.
char *buf = safe_malloc(buf_size);
size_t n_avail;
do {
n_avail = buf_size - n_read_total - 1;
if (n_avail < MIN_CHUNK_SIZE) {
// Double the buffer size.
n_avail += buf_size;
buf_size += buf_size;
buf = safe_realloc(buf, buf_size);
}
size_t n_read = fread(buf + n_read_total, 1, n_avail, f);
n_read_total += n_read;
} while (n_read == n_avail);
buf[n_read_total] = '\0';
return safe_realloc(buf, n_read_total + 1);
}