First of all, you need to decide whether you’re writing C or C++. C does not support classes, and you should not use C-style strings, I/O, and memory management routines in C++ code. Mixing elements of the two languages is a recipe for heartburn.
C and C++ are completely different languages that happen to share a lot of syntax and semantics, and a well-written C program doesn’t look or behave much like a well-written C++ program.
Now that the obligatory rant is out of the way, your two main type errors are as follows:
while(gets(*(myLines+s)) != ' ')
gets
(which you should never never never use in either C or C++ for any reason) returns a value of type char *
, but the character literal ' '
has type char
(in C++; in C, it has type int
). char
and char *
are different, incompatible types, and you cannot do comparisons between them.
Your other type error is
myWord[s] = strdup(myLines);
myLines
is an array of char *
, which in this context “decays” to type char **
. strdup
expects an argument of type char *
, hence the error. You need to pass a specific element of the array to strdup
:
myWord[s] = strdup( myLines[s] );
Additionally, you cannot compare C-style strings using the ==
or !=
operators; you must use a library function like strcmp
, such as
while ( strcmp( buffer, " " ) != 0 )
...
Note that we’re doing the comparison against the string literal " "
instead of the character literal ' '
.
If you want to write C code, then you need to change assem
from a class
to a struct
, and move the function delcarations outside of the struct
definition, and pass the struct type as an argument to the functions:
/**
* .h file
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct assem
{
char myString[101];
char *myLines[20];
int counter;
};
int readFile(FILE *FileToBeRead, struct assem *item );
int firstCheck( struct assem item );
void printFile( struct assem item);
Then you need to remove the assem::
prefix from your function definitions and use the struct assem
argument:
int readFile(FILE *file, struct assem *item)
{
size_t i = 0;
item->counter = 0;
/**
* get the number of array elements in item->myLines
*/
size_t maxLines = sizeof item->myLines / sizeof *item->myLines;
while( i < maxLines && fgets( item->myString, sizeof item->myString, file ) )
{
item->myLines[i] = strdup(item->myString);
i++;
item->counter++;
}
return 0;
}
void printFile( struct assem item )
{
printf("\n");
for(int s = 0; s < item.counter; s++)
{
printf("%s\n", item.myLines[s])); // use subscript notation; it's
// easier on the eyes
}
printf("\n");
}
int firstCheck( struct assem item )
{
char *myWord [7] = {NULL};
for(int s = 0; s < item.counter; s++)
{
/**
* In your original code, you were overwriting the myLines array,
* which contained what you read from the input file; I'm not sure
* you want to do that here, so I'm using myString instead.
*/
while( strcmp( fgets( item.myString, sizeof item.myString, stdin ), " " ) != 0 )
{
myWord[s] = strdup(item.myString);
}
}
/**
* At this point, you've dynamically allocated memory for the elements
* of the myWords array, but you aren't using the array outside of this
* function and you aren't freeing that memory when you're done, meaning
* you have a memory leak.
*
* If they myWords array doesn't need to exist outside of this function,
* then you need to free each element before exiting.
*/
return 0;
}
and then save all that as a .c file and compile it with a C compiler such as gcc
.
If you want to write C++ code, then you should use the fstream
, string
, and vector
types instead of FILE
and array types, and you should take advantage of C++ features like the std::copy
function template and stream iterators:
#include <string>
#include <vector>
#include <fstream>
#include <iterator>
#include <algorithm>
class assem
{
public:
// don't need the temporary myString buffer
std::vector< std::string > myLines;
// since vectors know how big they are, you don't need a separate
// counter attribute.
int readFile( std::istream& fileToBeRead );
int firstCheck( );
int printFile( );
};
int assem::readFile( std::istream& fileToBeRead )
{
/**
* Use the copy function template with a stream iterator to
* read the input file into your myLines vector
*/
std::copy(
std::istream_iterator<std::string>( fileToBeRead ), // start
std::istream_iterator<std::string>( ), // end
back_inserter( myLines ) // destination
);
return 0;
}
void assem::printFile( )
{
/**
* Use the same copy method to write each string in the myLines vector
* to standard output (again using a stream iterator), separated by
* newlines.
*/
std::cout << std::endl; // write the leading newline
std::copy(
myLines.begin(), // start
myLines.end(), // end
std::ostream_iterator< std::string >( std::cout, "\n" ) // destination
);
}
int assem::checkFirst( )
{
std::vector< std::string > myWords;
for ( std::vector::size_type s = 0; s < myLines.size(); s++ )
std::cin >> myWords;
return 0;
}
int main( void )
{
std::ifstream fileToBeRead( "myfile.txt" ); // or whatever its name is
if ( fileToBeRead )
{
assem myAssem;
myAssem.readFile( fileToBeRead );
fileToBeRead.close();
...
}
...
}
then save that as a .cpp file and compile it with a C++ compiler, such as g++
. Notice that with the C++ code you don’t need to muck with strdup
or worry about fixed array sizes, making the code a bit cleaner.
There are other issues with some of the program logic (what are the return values of readFile
and checkFirst
going to be used for, and is 0
the right value for that purpose), but this should at least get you on the right track.
Hopefully.
EDIT
I realized the logic in the C++ checkFirst
routine is not a correct translation of your original code. I know I said you shouldn’t mix C-style strings and I/O in C++ code, but sometimes you don’t have a choice. Here’s something that should be similar:
#include <cstring> // C++ header file for C-style string routines
...
char buf[N]; // N is large enough for your input plus 0 terminator
while ( std::cin.get( buf, sizeof buf ) && std::strcmp( buf, " " ) != 0 )
myWords.push_back ( std::string( buf ) );
1
solved C++ errors for C code