This would be the function I used
void put_partition_logical_block(int block_num)
{
// 写入逻辑块前要加上引导块的大小
fseek(fd, (block_num + 1) * LOGICAL_BLOCK_SIZE, SEEK_SET);
fwrite(logical_block, LOGICAL_BLOCK_SIZE, 1, fd);
fflush(fd);
}
void delete_hello(unsigned short id)
{
struct d_inode inode;
struct dir_entry dir;
get_inode(id, &inode);
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 64; j++)
{
get_partition_logical_block(inode.i_zone[i]);
memcpy(&dir, &logical_block[j * sizeof(dir)], sizeof(dir));
if (!strcmp(dir.name, "hello.c"))
{
memset(&logical_block[j * sizeof(dir)], 0, sizeof(dir));
put_partition_logical_block(inode.i_zone[i]);
return;
}
}
}
}
I made sure that it wasn't a permission issue or another program tying up, and that get_partition_logical_block function was fine
Related
Been working on this for 3 days and no progress, I'm still new to C.
What I'm trying to do is after getting data and stored into the struct RiderInfo.
void ridertopsort() is sorting based on the time.
void gettop() is to read what the racelength is and then store the data into tb struct. For now I'm trying to just figure out how to store the name only.
the 2nd and 3rd else if statement are bit different because I tried both ways in trying to copy name from Riderinfo to tb.
I'm not sure what I'm getting wrong, I can run the code but it exits directly without giving me any results and I know the problem is within the gettop() function.
struct shorrt
{
char topname[3][81];
int topagegroups[3];
int tophrs[3];
int topmin[3];
char botname[3][81];
int botagegroups[3];
int bothrs[3];
int botmins[3];
};
struct medium
{
char topname[3][81];
int topagegroups[3];
int tophrs[3];
int topmin[3];
char botname[3][81];
int botagegroups[3];
int bothrs[3];
int botmins[3];
};
struct lonng
{
char topname[3][81];
int topagegroups[3];
int tophrs[3];
int topmin[3];
char botname[3][81];
int botagegroups[3];
int bothrs[3];
int botmins[3];
};
struct tb
{
struct shorrt sr;
struct medium mr;
struct lonng lr;
};
struct RiderInfo
{
char name[81];
int age;
char raceLength;
int startTime;
int mountainTime;
int finishTime;
int withdrawn;
};
void ridertopsort(struct RiderInfo info[])
{
int i, j;
struct RiderInfo sorttemp;
for (i = 0; i < 5000; i++) {
for (j = i + 1; j < 5000; j++) {
if ((info[j].finishTime - info[j].startTime) < (info[i].finishTime - info[i].startTime))
{
sorttemp = info[j];
info[j] = info[i];
info[i] = sorttemp;
}
}
}
}
void gettop(struct RiderInfo info[], struct tb topbtm[])
{
int a,i,j,k,m;
m = 0;
i = 0;
a = type();
while(m == 0)
{
if (a == 1 && (info[i].raceLength == 's') || (info[i].raceLength == 'S'))
{
for (j = 0; j < 3; j++)
{
for (k = 0; k < 81; k++)
{
strcpy(info[i].name, topbtm->sr.topname);
if (j == 2)
{
m = 1;
}
}
}
}
else if (a == 2 && (info[i].raceLength == 'm') || (info[i].raceLength == 'M'))
{
for (j = 0; j < 3; j++)
{
for (k = 0; k < 81; k++)
{
strcpy(info[i].name, topbtm->mr.topname);
if (j == 2)
{
m = 1;
}
}
}
}
else if (a == 2 && (info[i].raceLength == 'l') || (info[i].raceLength == 'L'))
{
for (j = 0; j < 3; j++)
{
for (k = 0; k < 81; k++)
{
strcpy(info[i].name[k], topbtm->lr.topname[j][k]);
if (j == 2)
{
m = 1;
}
}
}
}
i++;
}
}
You need to address the fields of the instances of your structure, or use memcpy(). For example, when you write,
void ridertopsort(struct RiderInfo info[])
{
struct RiderInfo sorttemp;
// ...
You either can copy each field, with something like
memcpy(&sorttemp.name, &info[j].name, sizeof(sorttemp.name));
sorttemp.age = info[j].age;
// ...
Or copy the entire structure, with
memcpy(&sorttemp, &info[j], sizeof(sorttemp));
Also consider whether you really want three identical struct declarations. if you really, truly want to keep that, you probably want to code defensively, with a few lines such as,
static_assert( sizeof(sorttemp) == sizeof(info[0]), "" );
This will at least protect you from changing the size of one of your structures in a way that breaks existing code, although not from breaking layout compatibility while leaving the size the same.
This question already has answers here:
Why do I get a segfault in C from declaring a large array on the stack?
(5 answers)
Closed 3 years ago.
I am learning C and trying new things to test what I can do. I have written code which produces a Mandelbrot set with a given resolution (RES) which is #define RES in the .h file. This works and produces good output for resolutions less than 321. For some reason when RES > 321 then the code no longer executes.
I am running using GCC and plotting the output using Gnuplot. I have tried debugging with a debugger however for RES > 321 the main function no longer gets run? I have added a print in the first line of main() to see and this doesn't get run. An executable is made and the program compiles with no errors?
#include <stdio.h>
#include <math.h>
#define MAX_DEPTH 100
#define RES 321
typedef struct complex_t {
double re;
double im;
} complex;
void init_complex_grid(complex complex_grid[RES][RES], double left, double right, double top, double bottom);
int converge(complex a);
complex add_complex(complex a, complex b);
complex square_complex(complex a);
double mag_complex(complex a);
void output_grid(unsigned int grid[RES][RES]);
int main(void) {
// printf("HERE\n");
int i, j;
unsigned int convergence_grid[RES][RES];
complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
void init_complex_grid(complex complex_grid[RES][RES],
double left, double right,
double top, double bottom) {
int i, j;
double restep = (top - bottom) / RES;
double imstep = (right - left) / RES;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
complex_grid[i][j].re = left + j * imstep;
complex_grid[i][j].im = bottom + i * restep;
}
}
}
int converge(complex a) {
complex z = { 0, 0 };
int cnt = 0;
while (cnt <= MAX_DEPTH && mag_complex(z) <= 2) {
z = add_complex(square_complex(z), a);
cnt++;
}
return cnt;
}
complex add_complex(complex a, complex b) {
complex added = { a.re + b.re, a.im + b.im };
return added;
}
complex square_complex(complex a) {
complex b;
b.re = a.re * a.re - a.im * a.im;
b.im = 2 * a.re * b.im;
return b;
}
double mag_complex(complex a) {
return sqrt(a.re * a.re + a.im * a.im);
}
void output_grid(unsigned int grid[RES][RES]) {
FILE *f = fopen("mandelbrot.dat", "w");
int i, j;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
fprintf(f, "%d ", grid[i][j]);
}
fprintf(f, "\n");
}
fclose(f);
printf("\nFILE CLOSED\n");
}
I also added the line printf("\nFILE CLOSED\n"); so I would know that the output had been written to the file but this does not get run either with RES > 321.
You are defining too much data with automatic storage in the main() function: either make the large arrays global, static or allocate them from the heap.
Here is a simple fix you can try:
int main(void) {
int i, j;
static unsigned int convergence_grid[RES][RES];
static complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
Here is an alternative using heap allocation:
int main(void) {
int i, j;
unsigned int (*convergence_grid)[RES] = calloc(sizeof(*convergence_grid), RES);
complex (*complex_grid)[RES] = calloc(sizeof(*complex_grid), RES);
if (!convergence_grid || !complex_grid) {
fprintf(stderr, "cannot allocate arrays\n");
return 1;
}
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
free(complex_grid);
free(convergence_grid);
return 0;
}
I have a struct's array inside other struct's array and I wanna create a binary file which contains this data (only elements no null).
My structs are:
struct viaje {
char identificador[30+1];
char ciudadDestino[30+1];
char hotel[30+1];
int numeroNoches;
char tipoTransporte[30+1];
float precioAlojamiento;
float precioDesplazamiento;
};
struct cliente {
char dni[30+1];
char nombre[30+1];
char apellidos[30+1];
char direccion[30+1];
struct viaje viajes[50];
int totalViajes;
} clientes[20];
I am trying next:
// For create bin file
for (i = 0; i < totalClientes; i++) {
fwrite(clientes[i], sizeof(struct cliente), 1, fp_guardarCargarEstado);
for (j = 0; j < clientes[i].totalViajes; j++) {
fwrite(clientes[i].viajes[j], sizeof(struct viaje), 1, fp_guardarCargarEstado);
}
}
// For read bin file
for (i = 0; i < totalClientes; i++) {
fread(clientes[i], sizeof(struct cliente), 1, fp_guardarCargarEstado);
for (j = 0; j < clientes[i].totalViajes; j++) {
fread(clientes[i].viajes[j], sizeof(struct viaje), 1, fp_guardarCargarEstado);
}
}
I have not tryed fread yet due to I get two errors in fwrite: error: incompatible type for argument 1 of 'fwrite' and note: expected 'const void *' but argument is of type 'struct cliente'
Why could it be?
The fread and fwrite functions take a pointer to a memory location as their first parameter. You're instead passing an instance of a struct.
You need to pass in the address of this struct using the address-of operator &. Also, there's no need to write the struct viaje instances separately, since they are already contained within a struct cliente
// For create bin file
for (i = 0; i < totalClientes; i++) {
fwrite(&clientes[i], sizeof(struct cliente), 1, fp_guardarCargarEstado);
}
// For read bin file
for (i = 0; i < totalClientes; i++) {
fread(&clientes[i], sizeof(struct cliente), 1, fp_guardarCargarEstado);
}
It looks like there a a few things going on here. There are some important things to note here.
Location of totalViajes in struct cliente
The number of bytes you want to write in fwrite()
Resetting the FILE* before reading from the file again.
Here is what I used to test what I think you're looking for.
struct viaje {
char identificador[30+1];
char ciudadDestino[30+1];
char hotel[30+1];
int numeroNoches;
char tipoTransporte[30+1];
float precioAlojamiento;
float precioDesplazamiento;
};
struct cliente {
int totalViajes;
char dni[30+1];
char nombre[30+1];
char apellidos[30+1];
char direccion[30+1];
struct viaje viajes[50];
} clientes[20];
int main()
{
clientes[0].totalViajes = 1;
clientes[0].viajes[0].numeroNoches = 52;
int totalClientes = 1;
FILE* fp_guardarCargarEstado = fopen("myFile.bin", "wb");
// For create bin file
for (int i = 0; i < totalClientes; i++) {
fwrite(&clientes[i], sizeof(struct cliente)-(sizeof(struct viaje)*50), 1, fp_guardarCargarEstado);
for (int j = 0; j < clientes[i].totalViajes; j++) {
fwrite(&clientes[i].viajes[j], sizeof(struct viaje), 1, fp_guardarCargarEstado);
}
}
fclose(fp_guardarCargarEstado);
// set variables to 0 so you can tell if the read actually does anything
clientes[0].totalViajes = 0;
clientes[0].viajes[0].numeroNoches = 0;
fp_guardarCargarEstado = fopen( "myFile.bin", "rb" );
// For read bin file
for (int i = 0; i < totalClientes; i++) {
fread(&clientes[i], sizeof(struct cliente)-(sizeof(struct viaje)*50), 1, fp_guardarCargarEstado);
for (int j = 0; j < clientes[i].totalViajes; j++) {
fread(&clientes[i].viajes[j], sizeof(struct viaje), 1, fp_guardarCargarEstado);
}
}
fclose(fp_guardarCargarEstado);
printf("%i\n%i", clientes[0].totalViajes, clientes[0].viajes[0].numeroNoches );
return 0;
}
I'm trying to make a rehashing function that will work on very large hash tables (with more than 1 million entries) and my current method is very inefficient. Here are my structures
typedef struct {
int id, count, correct, valid;
char* word;
} Entry;
typedef struct {
Entry* arr;
int size, numValid;
} Hash;
Here is how it functions now (very slowly, not using memcpy):
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = calloc(hash->size, sizeof(Entry));
for(i = 0; i < hash->size; i++) {
if(hash->arr[i].count) {
tempArr[i].count = hash->arr[i].count;
tempArr[i].correct = hash->arr[i].valid;
tempArr[i].word = malloc(strlen(hash->arr[i].word) + 1);
strcpy(tempArr[i].word,hash->arr[i].word);
tempLen++;
}
memcpy(&tempArr[i],&hash->arr[i],sizeof(Entry));
tempArr[i] = hash->arr[i];
}
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word,tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
I'd prefer to use memcpy, but I can't for the life of me get it to work correctly. Here's what I'm trying (this is the code that doesn't work, and what I'm looking for help with):
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = calloc(hash->size, sizeof(Entry));
fprintf(stderr,"size: %d\n",hash->size * sizeof(Entry));
memcpy((tempArr),(hash->arr),hash->size * sizeof(Entry));
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word,tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
I'm sure it's an easy, one-line fix, but I just can't get myself to see it.
void addEntry(Hash* hash, char* tag, int count) {
int value = CHV(hash->size, tag), flag = 1, iter = 0;
int possIndex = findEntry(hash, tag);
/*fprintf(stderr,"AddEntry...\n");*/
if(possIndex >= 0) {
(hash->arr[possIndex].count)++;
return;
}
if((hash->size - hash->numValid) < ((double)hash->size / 10))
{
rehash(hash);
}
while(flag) {
iter++;
if(!(hash->arr[value].valid)) {
hash->arr[value].word = calloc(strlen(tag) + 1, sizeof(char));
strcpy(hash->arr[value].word, tag);
wordsAlloced++;
hash->arr[value].valid = 1;
hash->arr[value].correct = 1;
hash->arr[value].count = count;
flag = 0;
}
else {
value++;
if(value == hash->size) {
value = 0;
}
}
}
hash->numValid++;
}
I think that memcpy is no problem. problem is free all Entry by removeAllEntries(hash); then tempArr[i].word is the double free in free(tempArr[i].word); Because it's copied pointer. Also Using tempArr[i].word in addEntry(hash,tempArr[i].word,tempArr[i].count); is invalid. It's already free'd.
One solution proposes the use of realloc.
replace
void resize(Hash* hash) {
free(hash->arr);
hash->size *= 2;
hash->arr = calloc(hash->size, sizeof(Entry));
//TOTALALLOC += (hash->size * sizeof(Entry));
}
with
void resize(Hash* hash) {
Entry* tempArr;
if((tempArr = realloc(hash->arr, 2 * hash->size * sizeof(Entry)))==NULL){
fprintf(stderr,"failed realloc in resize.\n");
return ;
}
hash->size *= 2;
hash->arr = tempArr;
//TOTALALLOC += (hash->size * sizeof(Entry));
}
Does not rehash for resizing purpose.
Another solution
If rehashing is necessary for some reason. to change in the following
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = malloc(hash->size * sizeof(Entry));//Initialization isn't required because it is replaced by memcpy.
//fprintf(stderr,"size: %d\n",hash->size * sizeof(Entry));
memcpy(tempArr,hash->arr, hash->size * sizeof(Entry));
//To replicate word
for(i = 0; i < hash->size; i++) {
if(hash->arr[i].count) {
tempArr[i].word = malloc(strlen(hash->arr[i].word) + 1);
strcpy(tempArr[i].word, hash->arr[i].word);
}
}
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word, tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
If numValid is the represent the valid registration number, I think that it is sufficient to save only a word and count.
typedef struct{
int number;
char name[100];
} Apple
typedef struct{
Apple *apple;
int bit[2];
} AppleArray;
int main(){
AppleArray *aArray;
loadApple(&aArray);
}
loadApple(AppleArray **aArray){
*aArray = NULL;
for(i=0; i<100; i++){
*aArray = realloc(*aArray, (i+1) * sizeof(AppleArray));
/*SEGFAULT here*/
aArray[i]->apple = NULL;
for(j=0; j<2; j++){
aArray[i]->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1))
}
}
}
I want to have an AppleArray with specific size. Each AppleArray will have two Apple. However, I get segfault when i assign NULL to aArray[i]->apple. What is the problem there?
EDIT :
loadApple(AppleArray **aArray){
*aArray = malloc(100 * sizeof(AppleArray));
for(i=0; i<100; i++){
/*SEGFAULT here*/
aArray[i]->apple = NULL;
for(j=0; j<2; j++){
aArray[i]->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1))
}
}
}
You can call realloc() only on an address that was returned to you by an prior memory allocation function like malloc()or calloc() otherwise it gives you Undefined Behavior.
C99 Standard 7.20.3.4-3: The realloc function:
void *realloc(void *ptr, size_t size);
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined.
Apart from what Als has mentioned above, you are also having an array out-of-bounds read problem as after your loop, i value will be 100 and you are trying to access aArray[100] whereas in your logic (though incorrect) your would have allocated memory only till aArray[99].
Your loadApple function can be rewritten as below:
loadApple(AppleArray **aArray)
{
*aArray = NULL;
*aArray = malloc(100 * sizeof(AppleArray));
//I have shown index as 0 here just as an example.
(*aArray)[0].apple = NULL;
(*aArray)[0].apple = malloc(2 * sizeof(Apple));
}
This code should also give the same behavior which the logic of your code is trying to achieve.
<pre>
#include "stdio.h"
#include "stdlib.h"
#define MAX_SIZE 5
#define NAME_SIZE 100
#define APPLE_NUM 2
typedef struct
{
int number;
char name[NAME_SIZE];
}Apple;
typedef struct
{
Apple* apple;
int bit[2];
}AppleArray;
void printApple(AppleArray** aArray)
{
int i;
for (i = 0; i < MAX_SIZE; ++i)
{
fprintf(stderr, "%4d: bit[0] = %d, bit[1] = %d\n", i, (*aArray + i)->bit[0], (*aArray + i)->bit[1]);
int j;
for (j = 0; j < APPLE_NUM; ++j)
{
fprintf(stderr, "\tapple[%d]: number = %d, name = %s\n",
j,
(*aArray + i)->apple[j].number,
(*aArray + i)->apple[j].name);
}
printf("\n");
}
}
void loadApple(AppleArray **aArray)
{
*aArray = NULL;
int i;
for(i = 0; i < MAX_SIZE; i++)
{
AppleArray* tmp = (AppleArray*)realloc(*aArray, (i+1) * sizeof(AppleArray));
if (tmp != NULL)
{
*aArray = tmp;
}
else
{
//error
free(*aArray);
*aArray = NULL;
exit(0);
}
/*SEGFAULT here*/
//aArray[i]->apple = NULL;
(*aArray + i)->apple = NULL;
(*aArray + i)->bit[0] = i;
(*aArray + i)->bit[1] = i + 1;
/*
int j;
for (j = 0; j < 2; j++)
{
(*aArray + i)->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1));
}
*/
(*aArray + i)->apple = (Apple*)realloc(NULL, sizeof(Apple) * APPLE_NUM);
int j;
for (j = 0; j < APPLE_NUM; ++j)
{
(*aArray + i)->apple[j].number = j;
snprintf( (*aArray + i)->apple[j].name, NAME_SIZE, "apple_%d_%d", i, j);
}
}//for
}
void destroyApple(AppleArray* thiz)
{
if (thiz == NULL)
{
return;
}
int i;
for (i = 0; i < MAX_SIZE; ++i)
{
free(thiz[i].apple);
thiz[i].apple = NULL;
}
free(thiz);
}
int main()
{
AppleArray *aArray;
loadApple(&aArray);
printApple(&aArray);
destroyApple(aArray);
return 0;
}