Hey guys, I'm having another problem (two actually) with a function that reads 5 variables (type int) stored in an text file, separated by lines (\n) and then it returns them to use in the main() program.
The thing is, I do not know how to return them to the main program, probably using a typedef struct, but I never figured out how those worked (lousy teachers!), so I'm stuck. My other problem is quite odd, I'm using the function fgets() to read the values and then sscanf() to change them to int type, but the third is printing out as -858993460 something (all other 4 numbers are displayed correctly).

Here's the code for that function:

void Read_Environment() // It's void because I don't know how to return them yet
{
	char slight[4], spresence[2], stemperature[4], swind[4], shumidity[4]; // Strings, presence is either 0 or 1, all others vary from 0-100%
	int light, presence, temperature, wind, humidity;
	FILE *pf1 = fopen("environment.txt","r");
	if(!pf1)
	{
		printf("ERROR: Problem in file opening!\n");
	}
	else // Read data
	{
		fgets(slight, 4, pf1);
		sscanf(slight, "%d", &light);
		fgets(spresence, 2, pf1);
		sscanf(spresence, "%d", &presence);
		fgets(stemperature, 4, pf1);
		sscanf(stemperature, "%d", &temperature); // This one is printing -858993460 instead of the stored value
		fgets(swind, 4, pf1);
		sscanf(swind, "%d", &wind);
		fgets(shumidity, 4, pf1);
		sscanf(shumidity, "%d", &humidity);
		printf("%d\n%d\n%d\n%d\n%d", light, presence, temperature, wind, humidity); // For test purposes
		fclose(pf1);
	}
}

Sample of environment.txt file:

5
1
5
5
5

Output when running code:

5
1
-858993460
5
5

Since you don't check the return of fgets() for success, sscanf() is at the mercy of whatever got assigned into the variable stemperature

As a test, include printf("Show me what's in stemperature >>%s<<\n", stemperature); after fgets(stemperature, 4, pf1); to show you what I mean.
It is always a necessary practice to check the return of functions like fgets() and sscanf() for sucess.

I used your test and I got this output:

Show me what's in stemperature >>
<<

So... stemperature is getting an \n?

I used your test and I got this output:

Show me what's in stemperature >>
<<

So... stemperature is getting an \n?

The previous fgets(spresence, 2, pf1); is reading only part of the line, since 2 is not enough buffer to hold whatever the operating system puts into the file as return. That return is left behind, ready to be picked by the next fgets().
Increase spresence[] and the problem will not manifest as long as the integer will not overflow the buffer.

Well, what do you know? Problem solved! :) I would never have guessed it.
Thank you Aia!

That done, how do i return those values for use in if...else test function, for example, in main()?

>That done, how do i return those values for use in if...else test function, for example, in main()?
To return so many values a structure it is required.

Something like this:

typedef struct Environment
{
	int light;
	int presence;
	int temperature;
	int wind;
	int humidity;
};

Environment Read_Environment()
{
	char slight[4], spresence[4], stemperature[4], swind[4], shumidity[4];
	FILE *pf1 = fopen("environment.txt","r");
	if(!pf1)
	{
		printf("ERROR: Problem in file opening!\n");
	}
	else // Read data
	{
		fgets(slight, 4, pf1);
		sscanf(slight, "%d", Environment->light);
		fgets(spresence, 4, pf1);
		sscanf(spresence, "%d", Environment->presence);
		fgets(stemperature, 4, pf1);
		sscanf(stemperature, "%d", Environment->temperature);
		fgets(swind, 4, pf1);
		sscanf(swind, "%d", Environment->wind);
		fgets(shumidity, 4, pf1);
		sscanf(shumidity, "%d", Environment->humidity);
		fclose(pf1);
		return Environment;
	}
}

?

>?
I am afraid that would not even compile.
You are going to have to practice a little more with structures.
My suggestion is to avoid typedef for now.
I don't know how much it is going to help you, but here's some examples.

#include <stdio.h>

/* define structure of type example */
struct example {
	int a;
	int b;
};

/* prototype of structure example */
struct example exampleAtWork(struct example exampleParameter);

/* prototype of pointers to a structure example */
struct example *examplePointer(struct example *parameterPointer);

int main(void)
{
	struct example ecopy;
	struct example *copyPointer; /* a pointer */

       /* using a copy and not pointer */
	ecopy = exampleAtWork(ecopy);
	printf("Display value in ecopy.a: %d\n", ecopy.a);
	printf("Display value in ecopy.b: %d\n", ecopy.b);

       /* using a pointer as a parameter */
	examplePointer(&ecopy);
	printf("Display value in ecopy.a: %d\n", ecopy.a);
	printf("Display value in ecopy.b: %d\n", ecopy.b);

	/* Now using the returned pointer to example ecopy */
	copyPointer = examplePointer(&ecopy);

	/* Display using the copyPointer */
	printf("Display value in copyPointer->a: %d\n", copyPointer->a);
	printf("Display value in copyPointer->b: %d\n", copyPointer->b);

	return 0;
}

/*
 * define function to use the structure example
 * Parameter and return are copies which cost memory and process
 */
struct example exampleAtWork(struct example exampleParameter)
{
	exampleParameter.a = 1;
	exampleParameter.b = 2;
	return exampleParameter;
}
/*
 * the return is a pointer and the paramenter is a pointer
 * the benefit would be that instead of creating a whole copy,
 * it makes just a reference to the real structure.
 */
struct example *examplePointer(struct example *parameterPointer)
{
	parameterPointer->a = 3;
	parameterPointer->b = 4;
	return parameterPointer;
}

Yes, as I said before, structures are my week point! Thank you for the examples, they seem good and organized! I've been searching for good examples for ages! :)

Well, let's get back to work, any other doubt, I'll come back!

So here's what I'm trying to do, It compiles showing no errors, but it doesn't work, the program itself crashes when calling the function.

typedef struct
{
	int light;
	int presence;
	int temperature;
	int wind;
	int humidity;
}Variables;

Variables Read_Environment()
{
	Variables Environment;
	char slight[4], spresence[4], stemperature[4], swind[4], shumidity[4]; // Strings
	FILE *pf1 = fopen("environment.txt","r");
	fgets(slight, 4, pf1);
	sscanf(slight, "%d", Environment.light);
	fgets(spresence, 4, pf1);
	sscanf(spresence, "%d", Environment.presence);
	fgets(stemperature, 4, pf1);
	sscanf(stemperature, "%d", Environment.temperature);
	fgets(swind, 4, pf1);
	sscanf(swind, "%d", Environment.wind);
	fgets(shumidity, 4, pf1);
	sscanf(shumidity, "%d", Environment.humidity);
	fclose(pf1);
	return Environment;
}

Absolutely. It comes from a switch().

Variables Climate = Read_Environment();
			printf("%d\n%d\n%d\n%d\n%d\n", Climate.light, Climate.presence, Climate.temperature, Climate.wind, Climate.humidity);

Actually, when compiling it outputs 2 warning:

Compiling...
Autom.cpp
Autom.cpp(137) : warning C4715: 'Read_Environment' : not all control paths return a value
Autom.cpp(125) : warning C4700: local variable 'Environment' used without having been initialized
Linking...

Autom.exe - 0 error(s), 2 warning(s)

EDIT: Thank you, I'll try adding the &!
EDIT 2: The second warning appears no more.

All sscanf() need the &

sscanf(slight, "%d", &Environment.light);

Edited 3 Years Ago by Reverend Jim: Fixed formatting

Awesome!!! The program works! But what about the first warning?

Awesome!!! The program works! But what about the first warning?

>Autom.cpp(137) : warning C4715: 'Read_Environment' : not all control paths return a value
I am not familiar with that compiler error warnings, but my understanding is that there's not guarantee that Read_Environment function will return correctly.
Most likely, because Variables Environment is a local structure that could or could not receive proper values. That's my guess.

I can see, as well, you are compiling C code as it were C++.
Autom.cpp is for C++, proper C compiling should be *.c
Find the proper way of giving it the suffix .c in your compiler.

I'm using Microsoft Visual Studio 6.0 Standard Edition, It doesn't seem to contain natural C support, only C++.
When I created a new workspace and copied the code it gave me a whole bunch of new errors (for new file with *.c extension, just the warning for *.cpp)!

Compiling...
a.c
a.c(192) : error C2275: 'Variables' : illegal use of this type as an expression
        a.c(13) : see declaration of 'Variables'
a.c(192) : error C2146: syntax error : missing ';' before identifier 'Climate'
a.c(192) : error C2065: 'Climate' : undeclared identifier
a.c(192) : error C2115: '=' : incompatible types
a.c(193) : error C2224: left of '.light' must have struct/union type
a.c(193) : error C2224: left of '.presence' must have struct/union type
a.c(193) : error C2224: left of '.temperature' must have struct/union type
a.c(193) : error C2224: left of '.wind' must have struct/union type
a.c(193) : error C2224: left of '.humidity' must have struct/union type
Error executing cl.exe.

a.obj - 9 error(s), 0 warning(s)

I searched the msdn and got the answer, here: http://msdn.microsoft.com/en-us/library/aa734012(VS.60).aspx

So, how do I make

Environment Read_Environment()
{
	char slight[4], spresence[4], stemperature[4], swind[4], shumidity[4];
	FILE *pf1 = fopen("environment.txt","r");
	if(!pf1)
	{
		printf("ERROR: Problem in file opening!\n");
	}
	else // Read data
	{
        ....
        }
}

The first if(!pf1) return a value, like... Null?

>The first if(!pf1) return a value, like... Null?
No, it is not returning a NULL, if is evaluating the return of fopen()

Environment Read_Environment()
{
	char slight[4], spresence[4], stemperature[4], swind[4], shumidity[4];
	FILE *pf1 = fopen("environment.txt","r");
	if(!pf1)
	{
		printf("ERROR: Problem in file opening!\n");
               /* do something  more to ensure that the function Read_Enviroment will continue to exist, */
               /* or if it finished it will return a value */
       	}
	else // Read data
	{
        ....
        }
        /* need to return a structure Environment */
}

Yes, you're right, I have it like this:

Environment Read_Environment()
{
	char slight[4], spresence[4], stemperature[4], swind[4], shumidity[4];
	FILE *pf1 = fopen("environment.txt","r");
	if(!pf1)
	{
		printf("ERROR: Problem in file opening!\n");
                // I want the function to end here, if a problem is found
                // According to msdn this should also return a value, or:
                // warning C4715: 'Read_Environment' : not all control paths return a value
	}
	else // Read data
	{
        ....
        return Environment;
        }
}

When the error actually occurs (!pf1) is true, the program crashes (still displays the printf() message) with a windows debug error (the ones that ask to send to microsoft and you click no).

EDIT: Oh, I get it! Nevermind then! I put the return after the } as suggested, no more warnings!

This question has already been answered. Start a new discussion instead.