Implementation of Dynamic Table in C - c

Consider a dynamic table with the following properties:
Elements are stored in a dynamic array
Capacity is the size of the dynamic array
Size is defined is the number of elements stored in the array
Insert elements into this dynamic table. Double capacity if size is equal to capacity before push_back()
Don't use malloc or calloc functions.
Input: (n, elements)
9
6 7 8 12 4 10 11 1 15
Output:
capacity = 1; size = 1; elements = 6
capacity = 2; size = 2; elements = 6 7
capacity = 4; size = 3; elements = 6 7 8
capacity = 4; size = 4; elements = 6 7 8 12
capacity = 8; size = 5; elements = 6 7 8 12 4
capacity = 8; size = 6; elements = 6 7 8 12 4 10
capacity = 8; size = 7; elements = 6 7 8 12 4 10 11
capacity = 8; size = 8; elements = 6 7 8 12 4 10 11 1
capacity = 16; size = 9; elements = 6 7 8 12 4 10 11 1 15
#include <stdio.h>
int size=0;
int capacity=0;
int * double_capacity(int *a) {
int l=0;
if(capacity==0) capacity++;
capacity=capacity*2;
int b[capacity];
for(l;l<size;l++){
//printf("%d : %d \n",l,a[l]);
b[l]=a[l];
}
return b;
}
int * push_back(int *a,int j) {
if(size==capacity)
a=double_capacity(a);
a[size]=j;
size++;
int k=0;
printf("capacity = %d; size = %d; elements = ",capacity,size);
for(k=0;k<size;k++) {
printf(" %d",*(a+k));
}
printf("\n");
return a;
}
main() {
int *a;
int n,i,j,k,l;
scanf("%d",&n);
int temp[n];
for(i=0; i<n; i++) {
scanf("%d",&temp[i]);
}
for(i=0; i<n; i++) {
a=push_back(a,temp[i]);
}
}
it is showing compile error like
\temp.c: In function ‘double_capacity’:
temp.c:16:2: warning: function returns address of local variable [-Wreturn-local-addr]
return b;
^
even though i run this
when i gave input
3 3 2 1
output
capacity = 1; size = 1; elements = 3
capacity = 2; size = 2; elements = 3 2
capacity = 4; size = 3; elements = 3 2 1
when i gave input
5 5 4 3 2 1
output
capacity = 1; size = 1; elements = 5
capacity = 2; size = 2; elements = 5 4
capacity = 4; size = 3; elements = 5 4 3
capacity = 4; size = 4; elements = 0 0 -2128976676 2
capacity = 8; size = 5; elements = 0 0 -2128976676 32524 1

This won't work the way you want it to:
int * double_capacity(int *a)
{
int l=0;
if(capacity==0)
capacity++;
capacity=capacity*2;
int b[capacity];
for(l;l<size;l++)
{
//printf("%d : %d \n",l,a[l]);
b[l]=a[l];
}
return b;
}
The array b only exists for the lifetime of the double_capacity function; once the function exits, b no longer exists, and any pointer to it is now invalid.
You can't use VLAs this way.
I notice your instructions said nothing about the realloc function...
EDIT
If you cannot use any of the standard memory management functions (malloc, calloc, or realloc), then the only real alternative I can think of is to create your own memory pool and allocate your table elements from it.
Basically, you'd declare a large array of unsigned char at file scope like so:
#define HEAP_SIZE 8192 // 8 KB heap, use whatever size you need
static unsigned char heap[HEAP_SIZE];
then you'd grab chunks of this array to build your table. You'll need to do some bookkeeping to manage available and allocated blocks, their addresses and sizes within that array, etc. If you know what you're doing, this is a day or so of solid effort depending on how robust you want it to be.
Then again, there may be something a little more straightforward that I'm forgetting about. I just can't think of it at the moment.

Related

Place an array as an element to another array in C

I'm new to C and I'm having a hard time grasping the concept of making arrays.
I created the first 2d array to get the inputs by initializing the maximum possible entries I can have.
int max;
scanf("%d", &max);
int(*first)[n] = malloc(sizeof(int[n][n]));
After encoding the inputs, I have different unused space for every first[i] since each has different length. I received a memory limit exceeded so I would like to remove unused spaces. So, I created the second array and was planning to copy only the used spaces in the first array but I can't initialized the second array.
int second[n];
for (int i = 0; i < n; i++)
{
int len = length of first[i];
int length[len];
second[i] = length;
}
There are specialized data structures optimized for these cases, like sparse matrix, but they may be a bit difficult to implement depending on your level of knowledge.
An easy solution (at the cost of fragmenting the memory) is to use the first element of each row as a sentinel indicating the number of columns that the row is going to have, I omit the error checks for brevity:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand((unsigned)time(NULL));
size_t rows = (size_t)(rand() % 10 + 10);
int **array = malloc(sizeof *array * rows);
for (size_t row = 0; row < rows; row++)
{
int cols = rand() % 10 + 1;
array[row] = malloc(sizeof **array * (size_t)(cols + 1));
array[row][0] = cols;
for (int col = 1; col < cols + 1; col++)
{
array[row][col] = rand() % 10;
}
}
for (size_t row = 0; row < rows; row++)
{
int cols = array[row][0];
printf("%d cols: ", cols);
for (int col = 1; col < cols + 1; col++)
{
printf("%d ", array[row][col]);
}
printf("\n");
free(array[row]);
}
free(array);
return 0;
}
Output:
9 cols: 7 7 4 7 4 7 5 6 9
2 cols: 6 6
3 cols: 4 6 7
2 cols: 4 6
6 cols: 4 0 9 3 6 0
7 cols: 0 7 2 9 4 1 3
2 cols: 6 0
9 cols: 2 0 9 0 8 2 4 4 1
9 cols: 0 7 5 7 8 4 2 4 6
9 cols: 4 3 3 3 8 4 8 1 2
2 cols: 0 4
2 cols: 1 5
2 cols: 5 1
7 cols: 6 1 8 4 6 5 4
3 cols: 7 0 9
9 cols: 6 2 3 2 2 7 0 6 0
When you have a 2D array and don't know the size of each element, make an array of pointers. Then allocate exactly as much memory you need for each individual element.
A simple example would be storing each line of a file. Each line is an array of characters, but you don't know how long a line can be. It would be a huge waste to allocate a 2D array large enough to hold the biggest possible line. Instead, allocate a char **. This will be a list of char * strings.
const int max_lines = 1024;
char **lines = malloc(sizeof(char*) * max_lines);
This is 1024 pointers. Each pointer is only 4 or 8 bytes. So only about 8k of memory. There are ways to also avoid needing to allocate a fixed size here, but that's another answer.
Then read each line and only store as much as you need for each line.
int i = 0;
char line[BUFSIZ];
while( fgets(line, sizeof(line), stdin) ) {
lines[i] = strdup(line);
i++;
}
line is allocated using BUFSIZ to be large enough to fit most any line. And we reuse that to read lines of the file. But instead of storing all that extra memory, we use strdup to copy the line to the minimum memory and store a pointer to that in lines.

Iterating through array and shift elements to the end of the array

I'm trying to implement a simple game where the array symbolizes people standing in a circle, drawing an integer at the beginning of the game. each iteration is the size of the integer and removes people from the game.
so if array[]={a,b,c,d} and integer=3;
c is the first to be removed. Then b , then d. the winner is a.
at the end I need to print the array with the results by order of removal. so the printed array should be: a, d, b, c.
I'm trying to accomplish this only with use of pointers with no additional arrays.
Here's what i got, the problem is i'm trying to restart the for loop from the correct index and iterate through the remaining players who have not yet lost and cant get it right:
char *names[] = {"Tyrion Lannister","Daenerys Targaryen","Jon Snow","Arya Stark","Theon Greyjoy", "Joffrey Baratheon","Khal Drogo","Ted Mosby","Marshall Eriksen","Robin Scherbatsky","Barney Stinson", "Lily Aldrin", "Tracy McConnell", "Ted Mosby", "Leonard Hofstadter","Sheldon Cooper", "Penny", "Howard Wolowitz", "Raj Koothrappali", "Bernadette Rostenkowski-Wolowitz","Amy Farrah Fowler", "Gregory House", "Lisa Cuddy", "James Wilson","Eric Foreman", "Allison Cameron", "Robert Chase" ,"Lawrence Kutner", "Chris Taub","Remy 13 Hadley", "Amber Volakis"};
int Length = 31;
int number = 10;
char *tmp;
int i = 0, j;
int boom = number;
for (int i = number - 1; i < Length; i += boom - 1)
{
tmp = *(names + i);
for (int index = i; index < Length - 1; index++)
{
*(names + index) = *(names + index + 1);
}
*(names + Length - 1) = tmp;
Length--;
if (((number - 1) + i) >= Length)
{
int tempIndex = i;
i = tempIndex - Length;
printf("tmep index is %d, i is %d, Length is %d\n", tempIndex, i, Length);
}
}
for (i = 0; i < 31; i++)
printf("%s\n", names[i]);
I also tried another way with % operator, but couldn't quite get it done. Help would be much appreciated:
for (int i = number - 1; i < Length * (number - 1); i += boom - 1)
{
int t = i % Length;
printf("%d\n", t);
if (t < size)
{
counter++;
tmp = *(names + t);
// tmptwo = *(names + 31 - j);
for (int index = t; index < size - 1; index++)
{
*(names + index) = *(names + index + 1);
}
*(names + size - 1) = tmp;
size--;
printf("size %d\n", size);
}
}
You are thinking along the correct lines, but this is one circumstance where declaring and defining a simple function to shift elements down within an array moving the losing index to the end will simplify your life. By doing it this way, your only chores within the body of your code will be to provide the losing index and keeping track of the live number of players that remain with a simple counter.
An implementation of a function to move a given index to the last index for a given size could be similar to the following where a is the array to be reordered, elem_idx is the element index to move to the last element within sz elements:
void element_to_last (int *a, int elem_idx, int sz)
{
if (elem_idx > sz - 1) { /* valdate index in range */
fprintf (stderr, "error: index %d out of range for size %d\n",
elem_idx, sz);
return;
}
int i = elem_idx, /* declare, initialize i, tmp */
tmp = *(a + i);
if (elem_idx == sz - 1) /* elem_idx is last index */
return; /* no-swap */
for (; i < sz - 1; i++) /* loop shifting elements down */
*(a + i) = *(a + i + 1);
*(a + i) = tmp; /* set last to tmp */
}
(note: you will want to validate the element index to move to the end is within the valid range of indexes, and there is no need to perform the swap if the losing index is already the last in range).
A short working example where the WRAP constant simply controls output of no more than WRAP values per-line when printing results and the added DEBUG define allows outputting of additional information showing each operation if -DDEBUG is included in your compile string, e.g.
#include <stdio.h>
#ifndef WRAP
#define WRAP 10
#endif
void element_to_last (int *a, int elem_idx, int sz)
{
if (elem_idx > sz - 1) { /* valdate index in range */
fprintf (stderr, "error: index %d out of range for size %d\n",
elem_idx, sz);
return;
}
int i = elem_idx, /* declare, initialize i, tmp */
tmp = *(a + i);
if (elem_idx == sz - 1) { /* elem_idx is last index */
#ifdef DEBUG
fprintf (stderr, " index %d (%d) is last index %d - no swap.\n",
elem_idx, tmp, sz - 1);
#endif
return; /* no-swap */
}
#ifdef DEBUG
printf (" index %d (%d) to end %d\n", elem_idx, tmp, sz - 1);
#endif
for (; i < sz - 1; i++) /* loop shifting elements down */
*(a + i) = *(a + i + 1);
*(a + i) = tmp; /* set last to tmp */
}
void prn_array (int *a, int sz, int wrap)
{
for (int i = 0; i < sz; i++) {
if (i && i % wrap == 0)
putchar ('\n');
printf (" %2d", *(a + i));
}
putchar ('\n');
}
int main (void) {
int a[] = {0,1,2,3,4,5,6,7,8,9}, /* original array order */
sz = sizeof a/sizeof *a, /* nelem in original */
n = sz, /* n tracks remaining size */
loser[] = {2,0,7,3,2,3,2,1,1}, /* order of losing indexes */
lsz = sizeof loser/sizeof *loser; /* nelem in loser array */
puts ("before:");
prn_array (a, sz, WRAP);
puts ("\nelimination\n(remove indexes 2,0,7,3,2,3,2,1,1):");
for (int i = 0; i < lsz; i++) {
element_to_last (a, loser[i], n > 0 ? n-- : n);
prn_array (a, sz, WRAP);
}
puts ("\nafter:");
prn_array (a, sz, WRAP);
}
(note: the remaining players, e.g. the remaining number of elements is tracked with n while sz preserves the original size of the full array. lsz is used for the size of the loser array)
Example Use/Output
Without DEBUG defined, the output simply shows the state of the array after a loser is moved to the end of the remaining players:
$ ./bin/array_rotate
before:
0 1 2 3 4 5 6 7 8 9
elimination
(remove indexes 2,0,7,3,2,3,2,1,1):
0 1 3 4 5 6 7 8 9 2
1 3 4 5 6 7 8 9 0 2
1 3 4 5 6 7 8 9 0 2
1 3 4 6 7 8 5 9 0 2
1 3 6 7 8 4 5 9 0 2
1 3 6 8 7 4 5 9 0 2
1 3 8 6 7 4 5 9 0 2
1 8 3 6 7 4 5 9 0 2
1 8 3 6 7 4 5 9 0 2
after:
1 8 3 6 7 4 5 9 0 2
DEBUG Output
With DEBUG defined, additional information showing each index and (value) being moved to the end index shown, along with a note whether then end index was the loser in which case "no-swap" was attempted:
$ ./bin/array_rotate
before:
0 1 2 3 4 5 6 7 8 9
elimination
(remove indexes 2,0,7,3,2,3,2,1,1):
index 2 (2) to end 9
0 1 3 4 5 6 7 8 9 2
index 0 (0) to end 8
1 3 4 5 6 7 8 9 0 2
index 7 (9) is last index 7 - no swap.
1 3 4 5 6 7 8 9 0 2
index 3 (5) to end 6
1 3 4 6 7 8 5 9 0 2
index 2 (4) to end 5
1 3 6 7 8 4 5 9 0 2
index 3 (7) to end 4
1 3 6 8 7 4 5 9 0 2
index 2 (6) to end 3
1 3 8 6 7 4 5 9 0 2
index 1 (3) to end 2
1 8 3 6 7 4 5 9 0 2
index 1 (8) is last index 1 - no swap.
1 8 3 6 7 4 5 9 0 2
after:
1 8 3 6 7 4 5 9 0 2
Look things over and let me know if you have further questions.
This code should solve the problem by using modulo.
int size = 31;
int inc = 10;
for (int i = 0; i < size; i++)
{
int t = ((i + 1) * inc) % (size - i);
int *tmp = *(names + t);
printf("%d\n", t);
for (int j = t; j < (size - 1); j++)
{
*(names + j) = *(names + j + 1);
}
*(names + size - 1) = tmp;
}

Need a two-dimensional array of "variable" size in a struct

I am attempting to implement a grid of cells, analogous to that of Conway's game of life.
While each individual grid should have fixed size in both dimensions, I would like a Grid struct that allows for any size in both dimensions.
This is in analogy to how arrays can be of any size, but an array once initialized has a fixed size.
This is what I have so far:
typedef struct Cell {
int data;
// stuff to be added later
} Cell;
typedef struct Grid {
unsigned width;
unsigned height;
Cell cell[][];
} Grid;
Grid initGrid(unsigned width, unsigned height) {
Grid g;
g.width = width;
g.height = height;
g.cell = malloc( sizeof(Cell)*width*height );
return g;
}
However I get the following compile-time error:
main.c|12|note: declaration of `‘cell’ as multidimensional array must have bounds for all dimensions except the first|
How can I define a Grid data type with flexible size?
Post scriptum: as a C newbie, I thought the following would work:
typedef struct Grid {
unsigned width;
unsigned height;
Cell cell[width][height];
} Grid;
Post post scriptum: I am always uneasy whenever I use malloc. Am I doing (or trying to do) anything horribly wrong here?
You can't do it with double indexing (cell[x][y]) in C, there's no way to express that the number of bytes to jump for each row is dynamic.
So, the best (in my opinion) way to do is it to just do the indexing manually, using a one-dimensional array.
Put a plain:
Cell *cell;
in the struct (keeping width and height) and then index like so:
set_cell(Grid *g, unsigned int x, unsigned int y, Cell value)
{
g->cell[y * g->width + x] = value;
}
it's not unlikely that the compiler will inline this, and it's going to be pretty tight. Probably faster than the jagged array" approach which uses much more memory and another layer of indirection.
Allocation is simple:
Grid initGrid(unsigned int width, unsigned int height)
{
Grid g;
g.width = width;
g.height = height;
g.cell = malloc(width * height * sizeof *g.cell);
// add assert or error here, can't return NULL for value type
return g;
}
if you wanted to heap-allocate Grid too, you could co-allocate it with its elements.
And yes, you need to free() the allocation when you're done with it, in order to not leak memory. Strictly speaking on modern systems the OS will free all resources when the program ends anyway, but it's good form to free anyway:
void destroyGrid(Grid g)
{
free(g.cell);
}
You are pretty much out of luck here, as there is no way in C to use variable array lengths within a struct definition. What you can do is this:
typedef struct Grid {
unsigned width, height;
void* cell_internal; //Type: Cell(*)[height]
} Grid;
#define cell(myGrid) ((Cell(*)[(myGrid).height])(myGrid).cell_internal)
//in the constructor of Grid
newGrid->width = ...;
newGrid->height = ...;
cell(*newGrid) = malloc(newGrid->width*sizeof(*cell(*newGrid)));
for(unsigned x = 0; x < newGrid->width; x++) {
for(unsigned y = 0; y < newGrid->height; y++) {
cell(*newGrid)[x][y] = ...;
}
}
This is a dirty little hack, but it should work fine. The cool part is, that you can simply address your grid cells with cell(aGrid)[x][y]. The downside is, that it does obscure what is actually going on quite thoroughly. And there are not many people who can actually read what the cell() macro does. (Hint: It simply casts the void* to a pointer to a column array Cell(*)[myGrid.height], whatever myGrid.height may be at that point in time.)
Of course, you can go more explicit like this:
typedef struct Grid {
unsigned width, height;
void* cell_internal; //Type: Cell(*)[height]
} Grid;
//in the constructor of Grid
newGrid->width = ...;
newGrid->height = ...;
Cell (*cells)[newGrid->height] = malloc(newGrid->width*sizeof(*cells));
newGrid->cell_internal = cells;
for(unsigned x = 0; x < newGrid->width; x++) {
for(unsigned y = 0; y < newGrid->height; y++) {
cells[x][y] = ...;
}
}
The downside of this approach is, that you will need to explicitly create an alias pointer for the cell_internal pointer in each function that works on the cell data with
Cell (*cells)[myGrid->height] = myGrid->cell_internal;
Probably, this is the better approach, as it would seem to be readable to more people.
Use a flexible array. It's trivial to do with two malloc() calls, and possible to do with just one if you care to push the limits of alignment restrictions or strict aliasing or want to write the code to coerce the alignment of the portion of malloc()'d used to store Cell structures.
typedef struct Grid {
unsigned width;
unsigned height;
Cell *cell[];
} Grid;
Grid *initGrid(unsigned width, unsigned height )
{
// the Grid structure itself
size_t bytesNeeded = sizeof( Grid );
// space for pointers
bytesNeeded += height * sizeof( Cell * );
Grid *g = malloc( bytesNeeded );
g->width = width;
g->height = height;
// get all the data needed with one malloc call
g->cell[ 0 ] = malloc( width * height * sizeof( Cell ) );
// fill in the pointers
for ( unsigned ii = 1; ii < height; ii++ )
{
g->cell[ ii ] = g->cell[ 0 ] + ii * width;
}
return g;
}
void freeGrid( Grid *g )
{
free( g->cell[ 0 ] );
free( g );
}
If you don't mind pushing the limits of strict aliasing, you can do it with a flexible array and a single call to malloc() (it's left as an exercise for the reader to coerce the alignment of the data portion so that there's no potential alignment problems - that definitely is possible to do):
typedef struct Grid {
unsigned width;
unsigned height;
Cell *cell[];
} Grid;
Grid *initGrid(unsigned width, unsigned height )
{
// the Grid structure itself
size_t bytesNeeded = sizeof( Grid );
// space for pointers
bytesNeeded += height * sizeof( Cell * );
// space for data
bytesNeeded += width * height * sizeof( Cell );
Grid *g = malloc( bytesNeeded );
g->width = width;
g->height = height;
// fill in the pointers
// (technically a strict-aliasing/alignment violation as it assumes
// that &(g->cell[ height ]) is suitable to store a Cell...)
for ( unsigned ii = 0; ii < height; ii++ )
{
g->cell[ ii ] = ( Cell * ) &(g->cell[ height ]) +
ii * width;
}
return g;
}
following this excelent post:
How do I work with dynamic multi-dimensional arrays in C?
read #JensGustedt post and follow his link variable length arrays (VLAs)
there is actually a way - I followed his post and written a small test program to verify:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char ** argv)
{
unsigned int height = 100;
unsigned int width = 10;
int (*array)[width] = malloc (sizeof(int[height][width]));
array[90][2] = 1231;
printf("%d", array[90][2]);
}
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char ** argv)
{
unsigned int height;
unsigned int width;
int i,j;
printf("enter width: ");
scanf("%d", &width);
printf("enter height: ");
scanf("%d", &height);
int (*array)[width] = malloc (sizeof(int[height][width]));
for (i = 0; i < height; i++ )
for (j = 0; j < width; j++ )
array[i][j] = i;
for (i = 0; i < height; i++ ) {
for (j = 0; j < width; j++ )
printf("%d ", array[i][j]);
printf("\n");
}
}
and the console:
enter width: 10
enter height: 6
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5 5
I'll admit it suprising - I was not aware this exists...
EDIT - using structs:
#include <stdio.h>
#include <stdlib.h>
typedef struct Cell {
int data;
// stuff to be added later
} Cell;
typedef struct Grid {
unsigned width;
unsigned height;
Cell *cell;
} Grid;
Grid initGrid(unsigned width, unsigned height) {
Grid g;
g.width = width;
g.height = height;
g.cell = malloc( sizeof(Cell[height][width]) );
return g;
}
int main(int argc, char ** argv)
{
unsigned int height;
unsigned int width;
int i,j;
Grid test;
printf("enter width: ");
scanf("%d", &width);
printf("enter height: ");
scanf("%d", &height);
test = initGrid (width, height);
Cell (*array)[width] = test.cell;
for (i = 0; i < height; i++ )
for (j = 0; j < width; j++ )
array[i][j].data = i;
for (i = 0; i < height; i++ ) {
for (j = 0; j < width; j++ )
printf("%d ", array[i][j].data);
printf("\n");
}
}
console output:
enter width: 20
enter height: 10
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
there is a casting warning which i did not have time to resolve, but one can implement the idea - just do it cleanly... again it's a POC not an actual program

strings to array and locating a character in a string

i am working on a program where the input is an ID of 9 numbers :
program checks if the id is correct or not by :-
checking if the string is formed by numbers only .
every number has a weight of 1 or 2 so it should be 1 2 1 2 1 2 1 2
1
multiply the weight and the number
if the number is bigger than 9 then add the numbers forming it .
if the number is from multiplication of 10 then the ID is correct ..
example :-
1 7 9 3 7 9 2 5 0-ID
1 2 1 2 1 2 1 2 1-Weight
1 14 9 6 7 18 2 10 0-num x weight
1 5 9 6 7 9 2 1 0-(4)
sum = 40 then it is a correct ID.
I wrote most of it but then i noticed that it has to be a string . so my questions are :
is there a way to put a string into an array?as doing it with an
array is way easier.
how do i locate a place in a string ? like if i want the third
character in a string how do i locate it?.
and here is the code that i did it does not work yet and it needs alot of changes but i guess i will put it anyways :-
#include<stdio.h>
#define N 9
void input(int num[N]);
int check(int num[N]);
int main()
{
int num[N],a;
input(num);
a = check(num);
if (a = 1)
printf("ID is correct");
else printf("ID is NOT correct");
}
void input(int num[N])
{
int i;
printf("Enter your ID (9digits) :-");
for (i = 0;i < N;i++)
scanf("%d",num[i]);
}
int check(int num[N])
{
int w[N] = { 1,2,1,2,1,2,1,2,1 },wxnum[N],i,tota[N],sum,g;
for (i = 0;i < N;i++)
wxnum[i] = num[i] * w[i];
for (i = 0;i < N;i++)
{
if (wxnum[i] > 9)
tota[i] = wxnum[i] / 10 + wxnum[i] % 10;
else tota[i] = wxnum[i];
}
sum = tota[0] + tota[1] + tota[2] + tota[3] + tota[4] + tota[5] + tota[6] + tota[7] + tota[8];
g = sum % 10;
if (g = 0)
return 1;
else
return 0;
}
Thanks everyone for your help.
You can get a string by doing
/*N is defined as 9 in your code.*/
/*Considering there is always a '\0' in every string, we should allocat N + 1 slot for your nine numbers and the extra '\0'.*/
char chStr[N + 1];
scanf("%s", chStr);
After you got the string, you can take advantage of the values of charactor '0' - '9' (their values are from 48 to 57 correspondingly) in ASCII table, and easily transfer the charactors into integers by doing:
int i = 0;
for (i = 0; i < N; i++)
{
chStr[i] = chStr[i] - '0';
}
If you are restrict on the type, you can transfer these char values into int values by adding extra two lines:
int num[N];
int i = 0;
for (i = 0; i < N; i++)
{
chStr[i] = chStr[i] - '0';
num[i] = (int) chStr[i];
}
Please note that my code didn't check the validation of user input. To make it more secure, you can use
scanf("%9s", chStr);
to declare the maximum length that the user can input.

What should I do for sort array?

I tried to sort arr by excluding those who were already selected as the largest numbers but it didn't work.
The result is this:
As I intended, at first cycle, the store is {9, 0, 0, 0, 0 ... } and when arr[i] becomes 9, the rest of process should be skipped. I have to sort it without additional functions and it's too difficult to me. What is the problem?
int i = 0;
int j = 0;
int num = 0;
int sign = 0;
int arr[10] = { 1,5,3,4,8,7,5,9,8,0 };
int max = arr[0];
int store[10] = { 0 };
int k = 0;
for (j = 0; j < 10; j++) {
printf("store: ");
for (int n = 0; n < 10; on++)
printf("%d ", store[n]);
printf("\n");
for (i = 0; i < 10; i++) {
sign = 0;
k = 0;
while (k < 10) {
if (arr[i] == store[k]) {
sign = 1;
break;
}
k++;
}
if (sign == 1) {
continue;
}
if (arr[i] > max) {
max = arr[i];
}
}
store[j] = max;
}
You have several errors here:
The array store has a size of 10, but in the jth pass through the outer loop, only j values have been filled in; the rest is still zero. So whenever you iterate over store, you should use j as upper limit.
You are looking for the max in each iteration. Therefore, it is not enough to initialise max once outside the outer loop. You do that, and it will stay 9 ever after. You should reset max for every j.
Finally, your idea to go through the array to see whether you have already processed a certain value does not work. Your array has duplicates, two 8's and two 5's. You will only place one eight and one five with your strategy and re-use the last value of max for the last two elements. (Plus, that idea lead to O(n³) code, which is very wasteful.
You can work around that by keeping an extra array where you store whether (1) or not (0) you have already processed a value at a certain index or by setting processed entries in the array to a very low value.
What you want to implement is selection sort: Find the maximum value in the whole list and move it to the front. Then find the maximum in the whole list except the first item and move it to the second slot and so on:
* 1 5 3 4 8 7 5 9 8 0
9 * 5 3 4 8 7 5 1 8 0
9 8 * 3 4 5 7 5 1 8 0
9 8 8 * 4 5 7 5 1 3 0
9 8 8 7 * 5 4 5 1 3 0
9 8 8 7 5 * 4 5 1 3 0
9 8 8 7 5 5 * 4 1 3 0
9 8 8 7 5 5 4 * 1 3 0
9 8 8 7 5 5 4 3 * 1 0
9 8 8 7 5 5 4 3 1 * 0
9 8 8 7 5 5 4 3 1 0 *
Here, all items to the left of the asterisk have been sorted and everything to the right of the asterisk is still unsorted. When the * (at position j) has moved to the right, the whole array is sorted.
This sort is in-place: It destroys the original order of the array. That is useful, because the position of an element tells us whether it has been processed or not. In the third iteration, the algorithm can distinguish between the 8 that has been sorted and the 8 that hasn't been sorted yet. (This sort is often described as sorting a hand of cards: Look fo the lowest, put it to the left and so on. If you must sort into a second array, copy the original array and sort the copy in place.)
Here's the code that sorts your array and prints out the diagram above:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int arr[10] = {1, 5, 3, 4, 8, 7, 5, 9, 8, 0};
int i = 0;
int j = 0;
for (j = 0; j < 10; j++) {
int imax = j;
int swap = arr[j];
// print array
for (i = 0; i < 10; i++) {
if (i == j) printf("* ");
printf("%d ", arr[i]);
}
printf("\n");
// find index of maximum item
for (i = j + 1; i < 10; i++) {
if (arr[i] > arr[imax]) {
imax = i;
}
}
// swap first unsorted item and maximum item
arr[j] = arr[imax];
arr[imax] = swap;
}
// print fully sorted array
for (i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("*\n");
return 0;
}
Use i and j.
N is 10 and the data consists of shuffled numbers 0 to N-1.
j goes from 0 to N-1. At each step, you want to fill it with
the maximum of the unprocessed input.
So i goes from j+1 to N-1, in the inner loop. If arr[j] < arr[i],
swap arr[i] and arr[j].
It speeds up considerably as you get towards the end.

Resources