2

I'm new to pointers and I'm trying to implement a simple code, in which i read and write an array and I also search for the minimum element between two given indexes. For some reason the write() function prints large values (I'm guessing they are the locations in which values are stored). Also I receive a SIGSECV when I run the poz_minVal function. I know this is a nooby question, but any help will de much appreciated!

The code is as follows:

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

int read(int *v, FILE *f){
    int i,length;
    fscanf(f,"%d",&length);
    v = (int *)malloc(length*sizeof(int));
    for(i=0;i<length;++i)
        fscanf(f,"%d",v+i);
    return length;
}

void write(int *v, int length, FILE *g){
    int i;
    for(i=0;i<length;++i)
        fprintf(g,"%d ",*(v+i));
    fprintf(g,"\n\n");
}

int poz_valMin(int *v, int length,int left,int right){
    int k,mini = *v; //set mini as the 1st element in v
    for(k=left;k<right;++k)
        if(*(v+k) < mini)
            mini = *(v+k);
    return mini;
}

int main(){
    FILE *f = fopen("datein.txt","r");
    FILE *g = fopen("dateout.txt","w");
    int *v, n = read(v,f);
    write(v,n,g);
    fprintf("The minimum value between the indexes 2 and 4 is: %d.\n\n",poz_valMin(v,n,2,4));
    return 0;
}
theSongbird
  • 229
  • 1
  • 3
  • 13
  • Please show the input data. – Codor Jan 27 '17 at 11:20
  • which line ? where are the input datas? – Mohsen_Fatemi Jan 27 '17 at 11:22
  • 1
    You have made mistake with pointers !! :) – Prem KTiw Jan 27 '17 at 11:22
  • Also you forgot to free v. – Unick Jan 27 '17 at 11:23
  • 2
    Instead of `*(v+i)`, it's easier and more idiomatic to write `v[i]`. – G. Sliepen Jan 27 '17 at 11:26
  • for ease of readability and understand: 1) separate code blocks (for, if, else, while, do...while, switch, case, default) via a single blank line. 2) separate functions by 2 or 3 blank lines 3) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* – user3629249 Jan 28 '17 at 08:39
  • when calling any of the heap memory allocation functions (malloc, calloc, realloc), 1) do not cast the returned value. The returned value has type `void*` so can be assigned to any other pointer. 2) always check (!=NULL) the returned value to assure the operation was successful – user3629249 Jan 28 '17 at 08:46
  • when calling any of the `scanf()` family of functions, always check the returned value (not the parameter value) to assure the operation was successful. – user3629249 Jan 28 '17 at 08:47
  • when calling `fopen()`, always check (!=NULL) the returned value to assure the operation was successful – user3629249 Jan 28 '17 at 08:48
  • in the function: `read()`, the pointer `v` is on the stack. Changing that pointer has absolutely no effect on the `c` variable in the main() function. To correct that, the parameter needs to be `int **v` and the call to read() needs to be: `int n = read( &v, f);` – user3629249 Jan 28 '17 at 08:49
  • variable names should indicate `content` or `usage` (or better, both). Variable names like: `v`, `n`, are not meaningful, even in the current context – user3629249 Jan 28 '17 at 08:56
  • appropriate horizontal spacing will make the code much easier to read. Suggest spacing inside parens, after commas, and after semicolons in `for()` statements – user3629249 Jan 28 '17 at 09:01
  • the posted code doesn't even come close to compiling. Amongst other things, the first parameter to `fprintf()` is which output stream the data is written to. it should be: `fprintf( stdout, "The minimum value between the indexes 2 and 4 is: %d.\n\n", poz_valMin(v,n,2,4));` – user3629249 Jan 28 '17 at 09:07
  • why is the parameter `length` being passed to `poz_valMin()` when it is not being used? – user3629249 Jan 28 '17 at 09:08
  • when allocating memory from the heap, always pass the resulting pointer to `free()` before exiting the program. Do not leave the details to be cleaned up by the OS. – user3629249 Jan 28 '17 at 09:27
  • The posted code has a logic error. What happens if length' is 4 or less? – user3629249 Jan 28 '17 at 09:43

4 Answers4

3

Whatever barak manos has said is right, but let me point another way of defining read function.

int * read(FILE *f){
   int *v,length;
   fscanf(f,"%d",&length);
   v = (int *)malloc(length*sizeof(int));
   for(i=0;i<length;++i)
       fscanf(f,"%d",v+i);
   return v;
}


and then in main you should just write v = read(f);
This looks clean and simplifies the understanding.

A tip :
Once you notice that write is producing garbage, you should have printed the array v, and you could have caught the mistake !!

alk
  • 69,737
  • 10
  • 105
  • 255
Prem KTiw
  • 535
  • 1
  • 4
  • 17
  • 2
    Note that it is [redundant and potentially dangerous to cast the result of malloc and friends in C](http://stackoverflow.com/q/605845/253056). – Paul R Jan 27 '17 at 11:30
  • @alk This implementation is kinda awsome, thanks a lot for the idea! – theSongbird Jan 27 '17 at 14:46
  • 1
    @MattB: It's *prem ktiw*'s answer! I just corrected the grammar a bit. – alk Jan 27 '17 at 15:00
  • @MattB The implementation is just a tweaking in your code only. And you can give a +1 to the answer as well :) Thanks to `alk` for the correction . – Prem KTiw Jan 27 '17 at 15:00
2

Function read should take int** v, and assign *v = ....

Changing an input argument inside a function has no effect on the value of that argument outside the function.

barak manos
  • 29,648
  • 10
  • 62
  • 114
1
//int read(int *v, FILE *f) //<-- in this case v will be treated as local variable inside read() and not the parameter passed from main.
int read(int **v, FILE *f)
{
    int i,length;
    fscanf(f,"%d",&length);
    //v = (int *)malloc(length*sizeof(int));
    int *arr = (int *)malloc(length*sizeof(int));
    for(i=0;i<length;++i)
        //fscanf(f,"%d",v+i);
        fscanf(f,"%d",arr+i);

    *v = arr;  //now you are actually assigning the allocated memory to main::v
    return length;
}

read(&v,f);  //call read like this.
sameerkn
  • 2,209
  • 1
  • 12
  • 13
  • 2
    Note that it is [redundant and potentially dangerous to cast the result of malloc and friends in C](http://stackoverflow.com/q/605845/253056). – Paul R Jan 27 '17 at 11:30
1

the following code:

  1. incorporates the comments to the question, except good variable naming
  2. cleanly compiles
  3. performs the desired operation
  4. performs appropriate error checking

You should get in the habit of having the main() function (in those files that have a main() function) as the first function listed, Then use the appropriate 'prototype' statements for each of the sub functions

Suggest using size_t for values that must never be negative.

#include <stdio.h>  // fopen(), fclose(),
#include <stdlib.h>

size_t read(       int **v, FILE *f);
void   write(      int *v, size_t length, FILE *g );
int    poz_valMin( int *v, int left, int right );


int main( void )
{
    FILE *f = fopen("datein.txt","r");
    if( !f )
    {
        perror( "fopen for read of datain.txt failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    FILE *g = fopen("dateout.txt","w");
    if( !g )
    {
        perror( "fopen for write to dataout.txt failed" );
        fclose( f ); // cleanup
        exit( EXIT_FAILURE );
    }

    // implied else, fopen for output successful

    int *v;
    size_t n = read(&v,f);

    write(v,n,g);
    fprintf( stdout,
             "The minimum value between the indexes 2 and 4 is: %d.\n\n",
             poz_valMin(v, 2, 4));

    free( v );
    fclose( f );
    fclose( g );
}



size_t read(int **v, FILE *f)
{
    //int i;
    size_t length;

    if( 1 != fscanf(f,"%lu",&length) )
    {
        perror( "fscanf failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fscanf successful

    *v = malloc(length*sizeof(int));
    if( !v )
    {
        perror( "malloc failed" );
        fclose( f );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful

    for(size_t i=0; i<length; ++i)
    {
        if( 1 != fscanf(f,"%d",(*v)+i) )
        {
            perror( "fscanf for array values failed" );
            free( *v );
            fclose( f );
            exit( EXIT_FAILURE );
        }

        // implied else, fscanf successful
    }

    return length;
}


void write(int *v, size_t length, FILE *g)
{
    //int i;

    for( size_t i=0; i<length; ++i )
        fprintf(g,"%d ",*(v+i));

    fprintf(g,"\n\n");
}


int poz_valMin( int *v, int left, int right )
{
    int k;
    int mini = *v; //set mini as the 1st element in v

    for(k=left; k<right; ++k)
        if(*(v+k) < mini)
            mini = *(v+k);

    return mini;
}
user3629249
  • 16,402
  • 1
  • 16
  • 17