I have no idea how to attack this problem

C

Chad

say my input file is

[cdalten@localhost ~]$ more suck
______
< gnu? >
------
\ , ,
\ /( )`
\ \ \___ / |
/- _ `-/ '
(/\/ \ \ /\
/ / | ` \
O O ) / |
`-^--'`< '
(_.) _ ) /
`.___/` /
`-----' /
<----. __ / __ \
<----|====O)))==) \) /====
<----' `--' `.__,' \
| |
\ /
______( (_ / \______
,' ,-----' | \
`--{__________) \/




[cdalten@localhost ~]$

What I want to do is read this file in, store it in some kind of array
and then be able to print this on stdout. I thought maybe i could do
something like the following

read in each line of the art via fgets()
store each line in an array
repeat

now print the array that holds these lines


Chad
 
J

Jim Langston

Chad said:
say my input file is

[cdalten@localhost ~]$ more suck
______
< gnu? >
------
\ , ,
\ /( )`
\ \ \___ / |
/- _ `-/ '
(/\/ \ \ /\
/ / | ` \
O O ) / |
`-^--'`< '
(_.) _ ) /
`.___/` /
`-----' /
<----. __ / __ \
<----|====O)))==) \) /====
<----' `--' `.__,' \
| |
\ /
______( (_ / \______
,' ,-----' | \
`--{__________) \/




[cdalten@localhost ~]$

What I want to do is read this file in, store it in some kind of array
and then be able to print this on stdout. I thought maybe i could do
something like the following

read in each line of the art via fgets()
store each line in an array
repeat

now print the array that holds these lines

You don't even have to store them in an array. Just read a line, print a
line.

You didn't mention your langauge, it sounds like C but could be C++. Here
would be the C++ code, although it's not tested and may have bugs:

#include <ifstream>
#include <string>

int main()
{
std::ifsteam Input("suck");
std::string Line;
while ( std::getline( Input, Line ) )
std::cout << Line << "\n";
}

For C replace ifstream with whatever fgets uses (file?). Replace
std::string line with a c-style array char Line[100]; Replace the while
statement with whatever fgets returns on failure. Replace the std::cout
into output to std out.
 
K

Keith Thompson

Jim Langston said:
Chad said:
say my input file is

[cdalten@localhost ~]$ more suck [snip]
[cdalten@localhost ~]$

What I want to do is read this file in, store it in some kind of array
and then be able to print this on stdout. I thought maybe i could do
something like the following

read in each line of the art via fgets()
store each line in an array
repeat

now print the array that holds these lines

You don't even have to store them in an array. Just read a line, print a
line.

Sure, if all he wants to do is copy stdin to stdout. For that matter,
it's easier to do it a character at a time, and not significantly
slower.

But a program that reads an entire file, storing the contents
internally, and then prints it could be the basis for a program that,
for example, sorts the input or prints it in reverse order.

In C, you'll need to do some explicit dynamic allocation (assuming you
don't want to set fixed limits on either the number of lines or the
length of each line). See the malloc() and realloc() functions.

There are several ways to store the contents of a file in an array,
assuming it's a text file. You can store the entire file as a single
array of characters (with embedded '\n' characters marking ends of
lines), or you can store an array of lines. In the latter case,
you'll probably want a pointer to an array of char*, where each
element points to the first character of a string contaiing a copy of
one line.

Give us a better idea of what you're doing, and we can be more helpful.
You didn't mention your langauge, it sounds like C but could be C++. Here
would be the C++ code, although it's not tested and may have bugs:
[snip]

He implicitly mentioned the language by cross-posting to comp.lang.c.

Probably either comp.lang.c or comp.programming is appropriate. To
the original poster: I suggest picking one or the other, depending on
what kind of help you're looking for.

[snip]
 
M

Malcolm McLean

Chad said:
say my input file is

[cdalten@localhost ~]$ more suck
______
< gnu? >
------
\ , ,
\ /( )`
\ \ \___ / |
/- _ `-/ '
(/\/ \ \ /\
/ / | ` \
O O ) / |
`-^--'`< '
(_.) _ ) /
`.___/` /
`-----' /
<----. __ / __ \
<----|====O)))==) \) /====
<----' `--' `.__,' \
| |
\ /
______( (_ / \______
,' ,-----' | \
`--{__________) \/




[cdalten@localhost ~]$

What I want to do is read this file in, store it in some kind of array
and then be able to print this on stdout. I thought maybe i could do
something like the following

read in each line of the art via fgets()
store each line in an array
repeat

now print the array that holds these lines
You've got a 2d array of chars that make up the image. However you proably
don't know either dimension at compile time.
So you've got two choices of data structure

char *raster; /* malloced block to hold ASCII art image */
int width;
int height;

raster[y*width+x] = '*'; /* put a star at x, y */

or

char **lines; /* malloced list of pointer to lines */
int Nlines;
int linelen; /* this one you may not need if you put nuls on line
ends instead */

/* how to build the structure */
lines = malloc(Nlines * sizeof(char *));
for(i=0;i<Nlines;i++)
lines = malloc(linelen + 1);
lines[y][x] = '*'; /* put a star at x, y */

The second form has some advantages, for instance it is easier to expand or
shrink the image using realloc().
 
S

santosh

Message ID: said:
say my input file is

[cdalten@localhost ~]$ more suck
______
< gnu? >
------
\ , ,
\ /( )`
\ \ \___ / |
/- _ `-/ '
(/\/ \ \ /\
/ / | ` \
O O ) / |
`-^--'`< '
(_.) _ ) /
`.___/` /
`-----' /
<----. __ / __ \
<----|====O)))==) \) /====
<----' `--' `.__,' \
| |
\ /
______( (_ / \______
,' ,-----' | \
`--{__________) \/




[cdalten@localhost ~]$

What I want to do is read this file in, store it in some kind of array
and then be able to print this on stdout. I thought maybe i could do
something like the following

read in each line of the art via fgets()
store each line in an array
repeat

now print the array that holds these lines

It all depends on whether you want to read in the entire file into memory
before further processing or do it line by line, or even character by
character. You could also read in as an arbitrarily sized block, though
that's probably more common with non-text files.

To read in the entire file, I'd probably use getc in a loop with dynamic
buffer resizing, to accommodate more of the file, stopping when getc
returns EOF, for end-of-file or an error, or when memory allocation fails.

To read the file line by line, fgets is probably more appropriate for this
purpose. You might also consider using non-Standard but portable functions
like CBFalconer's ggets or Richard Heathfield's getline. In this scenario,
a dynamically allocated array of char * is probably most appropriate. Of
course, each of the char * must be further initialised to point to an array
of char to hold each line.

Your case is really no different from reading and writing any other text
file, regardless of the contents.
 
S

santosh

"]

Chad said:
say my input file is

[cdalten@localhost ~]$ more suck
______
< gnu? >
------
\ , ,
\ /( )`
\ \ \___ / |
/- _ `-/ '
(/\/ \ \ /\
/ / | ` \
O O ) / |
`-^--'`< '
(_.) _ ) /
`.___/` /
`-----' /
<----. __ / __ \
<----|====O)))==) \) /====
<----' `--' `.__,' \
| |
\ /
______( (_ / \______
,' ,-----' | \
`--{__________) \/




[cdalten@localhost ~]$

What I want to do is read this file in, store it in some kind of array
and then be able to print this on stdout. I thought maybe i could do
something like the following

read in each line of the art via fgets()
store each line in an array
repeat

now print the array that holds these lines
You've got a 2d array of chars that make up the image.[/QUOTE]

What image? It's a text file, composed of one or more lines.
However you proably
don't know either dimension at compile time.
So you've got two choices of data structure

char *raster; /* malloced block to hold ASCII art image */
int width;
int height;

raster[y*width+x] = '*'; /* put a star at x, y */

This is not an intuitive method for reading in a simple text file, though it
might be suitable for other purposes.
or

char **lines; /* malloced list of pointer to lines */
int Nlines;
int linelen; /* this one you may not need if you put nuls on
line ends instead */

/* how to build the structure */
lines = malloc(Nlines * sizeof(char *));
for(i=0;i<Nlines;i++)
lines = malloc(linelen + 1);
lines[y][x] = '*'; /* put a star at x, y */


Why put a '*'?
The second form has some advantages, for instance it is easier to expand
or shrink the image using realloc().

I'd probably encapsulate the "inner" loop, which reads in the lines, into a
separate function. This function would return to the caller when no more
char * are available to assign to lines. The caller would then expand the
char * array and call the inner function again, and so on till end-of-file
or error.
 
P

pete

Chad said:
say my input file is

[cdalten@localhost ~]$ more suck
______
< gnu? >
------
\ , ,
\ /( )`
\ \ \___ / |
/- _ `-/ '
(/\/ \ \ /\
/ / | ` \
O O ) / |
`-^--'`< '
(_.) _ ) /
`.___/` /
`-----' /
<----. __ / __ \
<----|====O)))==) \) /====
<----' `--' `.__,' \
| |
\ /
______( (_ / \______
,' ,-----' | \
`--{__________) \/

[cdalten@localhost ~]$

What I want to do is read this file in, store it in some kind of array
and then be able to print this on stdout. I thought maybe i could do
something like the following

read in each line of the art via fgets()
store each line in an array
repeat

now print the array that holds these lines

My preference for storing lines of a text file, is in a linked list.
I don't understand why you want to store the file contents
in memory prior to displaying it.
Without the storage, the whole program boils down to new.c

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
int c;
FILE *fp = fopen("file.txt", "r");

if (fp == NULL) {
puts("fp == NULL");
} else {
while ((c = getc(fp)) != EOF) {
putchar(c);
}
fclose(fp);
putchar('\n');
}
return 0;
}

/* END new.c */

type_1.c shows one way to read whole text files
into a linked list and display them.

/* BEGIN type_1.c */

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

#define INITIAL_BUFFER_SIZE 0
#define ARGV_0 "type_1"

struct list_node {
struct list_node *next;
void *data;
};

int get_line(char **lineptr, size_t *n, FILE *stream);
void list_free(struct list_node *node, void (*free_data)(void *));
int list_fputs(struct list_node *node, FILE *stream);
struct list_node *string_node(struct list_node **head,
struct list_node *tail,
char *data);

int main(int argc, char *argv[])
{
int rc;
FILE *fd;
char *buff_ptr;
size_t buff_size;
struct list_node *head, *tail;

if (argc > 1) {
buff_size = INITIAL_BUFFER_SIZE;
buff_ptr = malloc(buff_size);
if (buff_ptr == NULL && buff_size != 0) {
printf("malloc(%lu) == NULL\n", (long unsigned)buff_size);
exit(EXIT_FAILURE);
}
tail = head = NULL;
while (*++argv != NULL) {
fd = fopen(*argv, "r");
if (fd != NULL) {
while ((rc = get_line(&buff_ptr, &buff_size, fd))
{
tail = string_node(&head, tail, buff_ptr);
if (tail == NULL) {
break;
}
}
fclose(fd);
switch (rc) {
case EOF:
if (buff_ptr != NULL
&& strlen(buff_ptr) != 0)
{
puts("rc equals EOF\n"
"The string in buff_ptr is:");
puts(buff_ptr);
tail = string_node(&head, tail, buff_ptr);
}
break;
case 0:
puts("realloc returned a null pointer "
"value in line_to_string.");
if (buff_size > 1) {
puts("rc equals 0\n"
"The string in buff_ptr is:");
puts(buff_ptr);
tail = string_node(&head, tail, buff_ptr);
}
break;
default:
puts("malloc problem in string_node.");
break;
}
} else {
printf("\nfopen() problem with \"%s\"\n", *argv);
break;
}
list_fputs(head, stdout);
list_free(head, free);
head = NULL;
}
free(buff_ptr);
} else {
puts("Usage:\n>" ARGV_0
" <TEXT_FILE_0> <TEXT_FILE_1> <TEXT_FILE_2> ...\n");
}
return 0;
}

int get_line(char **lineptr, size_t *n, FILE *stream)
{
int rc;
void *p;
size_t count;

count = 0;
while ((rc = getc(stream)) != EOF) {
if (count != -1) {
++count;
}
if (count + 2 > *n) {
p = realloc(*lineptr, count + 2);
if (p == NULL) {
if (*n > count) {
(*lineptr)[count] = '\0';
(*lineptr)[count - 1] = (char)rc;
} else {
if (*n != 0) {
**lineptr = '\0';
}
ungetc(rc, stream);
}
count = 0;
break;
}
*lineptr = p;
*n = count + 2;
}
if (rc == '\n') {
(*lineptr)[count - 1] = '\0';
break;
}
(*lineptr)[count - 1] = (char)rc;
}
if (rc != EOF) {
rc = count > INT_MAX ? INT_MAX : count;
} else {
if (*n > count) {
(*lineptr)[count] = '\0';
}
}
return rc;
}

void list_free(struct list_node *node, void (*free_data)(void *))
{
struct list_node *next_node;

while (node != NULL) {
next_node = node -> next;
free_data(node -> data);
free(node);
node = next_node;
}
}

int list_fputs(struct list_node *node, FILE *stream)
{
while (node != NULL) {
if (fputs(node -> data, stream) == EOF) {
return EOF;
}
if (putc('\n', stream) == EOF) {
return EOF;
}
node = node -> next;
}
return '\n';
}

struct list_node *string_node(struct list_node **head,
struct list_node *tail,
char *data)
{
struct list_node *node;

node = malloc(sizeof *node);
if (node != NULL) {
node -> next = NULL;
node -> data = malloc(strlen(data) + 1);
if (node -> data != NULL) {
strcpy(node -> data, data);
if (*head == NULL) {
*head = node;
} else {
tail -> next = node;
}
} else {
free(node);
node = NULL;
}
}
return node;
}

/* END type_1.c */
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top