/r/cprogramming
A Subreddit dedicated to the C programming language. Everything related to C is welcome here.
C is a general-purpose, procedural computer programming language supporting structured programming, lexical variable scope, and recursion, with a static type system. By design, C provides constructs that map efficiently to typical machine instructions. It has found lasting use in applications previously coded in assembly language. Such applications include operating systems and various application software for computer architectures that range from supercomputers to PLCs and embedded systems. Wikipedia
Imperative (procedural), structured
Dennis Ritchie
Dennis Ritchie & Bell Labs (creators);
ANSI X3J11 (ANSI C);
ISO/IEC JTC1/SC22/WG14 (ISO C)
1972 (48 years ago)
C18 / June 2018 (2 years ago)
Static, weak, manifest, nominal
Cross-platform
.c for sources
.h for headers
C++ is not C (but C can be C++)
For C++ go to :
Other Resources
/r/cprogramming
lets say the program is
void fun( float a=8,float b=3.7) { printf("%d,%f",a,b); }
how do i change the value of b lets say to 5.8 without interfering with a.
and also is there any error in my function as i tried in online compiler and i was getting this error
error: expected ';', ',' or ')' before '=' token
Here's a couple of snippets from a project I just started (made sure it works 1st)
GNUmakefile
GOALS:=$(or $(MAKWCMDGOALS),build)
export
$(GOALS):
$(CC) -E -x c -traditional-cpp -o tmp.mak -c ffxv-cheater.mak
make -f tmp.mak $(GOALS)
# $(RM) tmp.mak
ffxv-cheater.mak
#if 0
// This file is to be compiled into the actual makefile that will be run
#endif
NAME:=ffxv_s-cheater
#ifdef _WIN32
OUT:=$(NAME).exe
#else
OUT:=$(NAME).elf
#endif
build: $(OUT)
$(OUT): $(NAME).c
$(CC) -o $@ $<
Hi, i tried the following code, and it compiles and runs with gcc 11.4.0 and flags -Wall and -Werror :
#include <stdio.h>
enum fd_enum;
void print_enum(enum fd_enum);
enum fd_enum {
VAL_0 = 1UL << 40,
VAL_1
};
int main(void)
{
print_enum(VAL_1);
return 0;
}
void print_enum(enum fd_enum val)
{
If (val == VAL_0) {
printf("VAL_0 = %lu\n", val);
} else {
printf("VAL_1 = %lu\n", val);
}
}
When declaring print_enum()
, the enum size is not known yet. I manually forced the enum to be larger than an int
incase the compiler chosed this type by default if the enum is not defined yet. But apparently this doesn't even generate a warning and works fine, how ?
Text file treated as binary
I have a text file that is being treated as binary file when using grep without -a flag(because sometimes it contains null bytes in the file)...the text file is the output of c program...
Any way to check why this happening or how to debug this?
I'm using sokol for a simple project; it uses a custom compiler for certain .glsl files, called sokol-shdc. Apparently, it's suppose to have great IDE support, so then, how would I integrate it with meson?
I'm a relatively new programmer that is quite familar with C. Unfortunately, I havent gotten a clue when it comes to C's build systems, especially Meson. Worse yet, I'm trying to configure it with Sokol: a header only graphics library. Got any tips or tutorials?
I'm sure it has to do with operator precedence and order of evaluation, but I'm not understanding why.
Why is an ++ suffix in parentheses evaluated after the indirection outside of them?
And if the indirection is evaluated before the expression in the parentheses, why is the += operator evaluated first, even though it has a much lower precedence than the indirection operator?
I'm on Windows 64-bit and using gcc -std=c17 to compile.
Folks working in "operating systems" and "distributed systems" field, what kinds of projects are you guys working on in the company or personally? Can you share what kind of problems you guys are solving? Feel free to share details if possible even though it may be highly technical. TYIA.
Here's what I got (don't mind the pawmsg stuff, it's gonna be embedded in a library of mine that's always paired with a launcher).
extern char **environ;
__thread size_t tenviron_total = 0;
__thread size_t tenviron_count = 0;
__thread char **tenviron = NULL;
void term_tenviron(void)
{
if ( !tenviron )
{
tenviron_size = 0;
tenviron_used = 0;
return;
}
size_t i = tenviron_count;
while ( i-- )
{
free( tenviron[i] );
tenviron[i] = NULL;
}
free( (void*)tenviron );
tenviron_total = 0;
tenviron_count = 0;
tenviron = NULL;
}
int init_tenviron(void)
{
if ( tenviron )
return 0;
size_t count = 0, size = 0;
while ( environ[count] ) ++count;
tenviron = calloc( count * 2, sizeof(char*) );
if ( !tenviron )
{
pawsetmsg( PAWMSGID_NOT_ENOUGH_MEMORY, 0 );
return -1;
}
tenviron_total = count * 2;
for ( size_t i = 0; i < count; ++i )
{
char *srcpair = environ[i];
char **dstpair = tenviron + i;
size_t len = strlen( srcpair );
*dstpair = malloc( len + 1 );
if ( !(*dstpair) )
{
tenviron_count = i;
term_tenviron();
pawsetmsg( PAWMSGID_NOT_ENOUGH_MEMORY );
return -1;
}
memcpy( *dstpair, srcpair, len + 1 );
}
return 0;
}
char **newenvpair( void )
{
size_t i = tenviron_count;
if ( i >= tenviron_total )
return NULL;
tenviron_count++;
return tenviron + i;
}
bool isenvkeyvalid( char const *key )
{
if ( !key || strchr( key, '=' ) )
{
pawsetmsg( PAWMSGID_ERRORS_ENCOUNTERED, 0 );
return false;
}
return true;
}
char **getenvpair( char const *key )
{
if ( init_tenviron() != 0 )
return NULL;
size_t const count = tenviron_used / sizeof(char*);
for ( size_t i = 0; i < count; ++i )
{
char const *pair = tenviron[i];
if ( !pair )
continue;
if ( strstr( pair, key ) == pair )
return tenviron + i;
}
return NULL;
}
/* Override the symbols to be thread safe */
char *getenv( char const *key )
{
char **pair = getenvpair(key);
return pair ? strchr( *pair, '=' ) + 1 : NULL;
}
int unsetenv( char const *key )
{
char **pair = getenvpair(key);
if ( pair )
{
size_t i = mpawabs_bytediff( (void**)pair, (void**)tenviron ).abs / sizeof(char*);
free( *pair );
/* We move the pointers so the system can read it correctly if and
* when we override environ */
memmove
(
(void*)(tenviron + i),
(void*)(tenviron + i + 1),
(tenviron_count - i - 1) * sizeof(char*)
);
tenviron[--tenviron_count] = NULL;
return 0;
}
return -1;
}
int putenv( char const *keyval )
{
char *val = keyval;
char *key = strtok_r( keyval, "=", &keyval );
size_t keylen = strlen(key);
size_t vallen = strlen(val);
char **next = newenvpair();
char **pair = getenvpair(key);
if ( isenvkeyvalid(key) || !next )
return -1;
if ( pair )
{
old = *pair;
next = pair;
}
*next = malloc( keylen + vallen + 2 );
if ( !(*next) )
{
if ( pair )
*pair = old;
return -1;
}
memcpy( *next, key, keylen );
(*next)[keylen] = '=';
memcpy( *next + keylen + 1, val, vallen + 1 );
return 0;
}
int setenv( char const *key, char const *val, int replace )
{
size_t keylen = strlen(key);
size_t vallen = strlen(val);
char **next = newenvpair();
char **pair = getenvpair(key), *old = NULL;
if ( isenvkeyvalid(key) || !next )
return -1;
if ( pair )
{
if ( !replace )
return 0;
old = *pair;
next = pair;
}
*next = malloc( keylen + vallen + 2 );
if ( !(*next) )
{
if ( pair )
*pair = old;
return -1;
}
memcpy( *next, key, keylen );
(*next)[keylen] = '=';
memcpy( *next + keylen + 1, val, vallen + 1 );
return 0;
}
Suggest me some good ones that I can do in C or Rust. Distributed systems, operating systems domain.
When you assign 7.0 to both integer variable and float variable they return true and execute first line of print statement but further any addition of decimal points executes else condition
I am an engineer from a electrical and electronic engineering background. In the early days of university I was able to get some hands on experience with C, but ever since never touched it at all. So recently I have slowly going through a Udemy course to get me back on track. The thing is I want to learn C through the use of an text editor (VS Code) and to make this even more hard on a Linux laptop (don't even ask). On the course they suggest using code lite, but from my experience dedicated IDE has always been troublesome with me so I want to try my luck with VS Code.
I want to know the set up (and easy one if that is possible) on setting out VS code to be blasting through C like know ones business!!!
Struct l{
Int num;
} If I have a variable within a struct like l->num isn't that a pointer?
So why wouldn't I dereference it like *l->num?
Rather than int a = l->num?
Shouldn't it be int a = *l->num?
I.mean if I have
Int *ptr = &a;
Then I'd do int c = *ptr, not int c = ptr. Since ptr is an address.
So isn't l->num also an address and I want the contents of that address and not l->num the address?
I have within my struct line the variable x.
How do I increment
Line->x without doing line->x = line->x + 1;?
Can I do this for example.... line->x++?
Thanks
Hi all,
I'm trying to figure out a way to pass the stdout
handle from a child process up to a parent so the parent can make use of the console created for the child. I'm having a hell of a time getting it to work and can't find anything online, it seems like everything is targetted towards a child inheriting a parent's handle which doesn't work for what I'm trying to do.
The end goal is that I want multiple consoles for the parent process but as far as I can tell on Windows you can only have a single console per process. My solution to this was to be creating a child process with a console and then passing a handle back up to the parent so it could control the child console. It seems this kind of thing is typically done by creating a pipe and just throwing data down it for the child to print but I would like to have more control then that.
I need the child stdout handle to use in SetConsoleTextAttribute()
and the stdout FILE *
to use with fprintf()
and similar.
Has anyone got any ideas on how to do this? I've been spinning wheels for a while and am not having not luck. I can get the processes to spawn and pass messages between threads but have had no luck with getting the parent to take over the child console.
I suppose the fallback is sending the strings over a pipe and then requesting console attribute changes via messages or something but I'd like to avoid that if at all possible as it would involve heavy refactoring of the debug library I've build which relies heavily on macros.
I was thinking of a linked list that could store various info about each line in a text editor.
For example, where the cursor is or was before using arrow to move to adjacent line, where the line begins and ends in memory etc.
Is a linked list or array of structs best for this?
For example, if I'm using an array of structs I could have vars in the structs that point to the above and bottom lines so that I could move between them on the ncurses window and also the corresponding address in memory.
Or each time the user presses enter I can malloc a new struct with all the info about the current lines address etc.
This is fun!
Thanks
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <stdbool.h>
6
7 void clear_input_buffer();
8
9 int main()
10 {
11 char input[100];
12 //char delim[] = {'\n', ' ', ','};
13 float a, b, c;
14
15 while (1)
16 {
17 printf("Please Enter Numbers with Separators: ");
18 if (fgets(input, sizeof(input), stdin) == NULL){printf("Error Reading Output");clear_input_buffer();continue;}
19 for (int i = 0; input[i] != '\0'; i++)
20 {
21 if (!isdigit(input[i]) && input[i] != ' ' && input[i] != ',' && input[i] != '\n')
22 {
23 break;
24 }
25 }
26
27 char *token1 = strtok(input," ,\n");
28 a = atof(token1);
29 char *token2 = strtok(NULL," ,\n");
30 b = atof(token2);
31 char *token3 = strtok(NULL," ,\n");
32 c = atof(token3);
33 if (strtok(NULL, " ,\n") != NULL)
34 {
35 printf("Too many inputs. You only need 3\n");
36 continue;
37 }
38 printf("A = %.1f\nB = %.1f\nC = %.1f\nSum: %.1f\n", a, b, c, a + b + c);
39
40
41
42
43
44 }
45 return 0;
46
47
48 }
49
50
51
52 void clear_input_buffer()
53 {
54 while (getchar() != '\n');
55 }
#include <stdio.h>
void quicksort(int *a, int l, int h) { if (l < h) { int p = a[h]; int i = l - 1; int j; for (j = l; j < h; j++) { if (a[j] < p) { int t = a[++i]; a[i] = a[j]; a[j] = t; } } a[h] = a[++i]; a[i] = p; quicksort(a, l, i - 1); quicksort(a, i + 1, h); } }
int main() { int n, i; printf("Enter the number of elements: "); scanf("%d", &n); int a[n]; printf("Enter %d elements:\n", n); for (i = 0; i < n; i++) { scanf("%d", &a[i]); } quicksort(a, 0, n - 1); printf("Sorted array: "); for (i = 0; i < n; i++) { printf("%d ", a[i]); } return 0; }
Hello all,
I need to create a program that counts the number of lines, sentences, and words from a given file. The captured data should be written to another file, and all words should be printed to the console. During the learning process, I have encountered many ways to implement this program, but as a beginner, I am unsure which approach would be the most efficient and suitable for this task. I am also considering whether to print the words to the console character by character or by whole words. Thank you for any advice, and I can also send the code I have so far. Thank you for the help. Here is something what I've done :
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
void statistics(FILE *input_file, FILE *output_file); // function declaration that counts the given values
bool isSentenceEnd(char character);
bool isWordEnd(char character);
int main(void)
{
char input_file[32]; // array for the name of the input file to read from
char output_file[32]; // array for the name of the output file to write to
printf("Enter the name of the input file: \n");
if (scanf("%31s", input_file) != 1 || input_file[0] == '\0') // checking if the input is valid or empty
{
printf("Error loading input file!\n");
return 1;
}
printf("Enter the name of the output file: \n");
if (scanf("%31s", output_file) != 1 || output_file[0] == '\0') // checking if the input is valid or empty
{
printf("Error loading output file!\n");
return 1;
}
FILE *fr = fopen(input_file, "r"); // create a FILE pointer (fr=file_read) to open the found file "r" = read mode
if (fr == NULL)
{
perror("Error opening file for reading\n"); // perror = prints detailed error message
return 1;
}
printf("File %s opened for reading\n", input_file);
FILE *fw = fopen(output_file, "w"); // create a FILE pointer (fw=file_write) to open the file for writing "w" = write mode
if (fw == NULL)
{
perror("Error opening output file for writing.\n");
fclose(fr); // if opening the output file fails, we close the input file to prevent memory leaks
return 1; // end the program with an error
}
statistics(fr, fw); // function that performs writing the given values and printing words to the console
// after execution, we close the used files to free the allocated memory from fopen()
fclose(fr);
fclose(fw);
return 0;
}
bool isSentenceEnd(char character)
{
return character == '?' || character == '!' || character == '.';
}
bool isWordEnd(char character)
{
return isSentenceEnd(character) || character == ' ' || character == '\n' || character == ',' || character == ';';
}
// definition of the created function
void statistics(FILE *input_file, FILE *output_file)
{
int line_counter = 0; // line counter - terminated by '\n'
int word_counter = 0; // word counter
int sentence_counter = 0; // sentence counter - terminated by . ? !
char character;
char word[64]; // array for capturing found words, [64] because we expect that no word will be longer, question of dynamic allocation, why is it not needed
int word_index = 0;
while ((character = getc(input_file)) != EOF)
{
if (isalnum(character)) {
if (word_index < 63) {
word[word_index++] = character; // alternative solution where you directly print it but don't count words
}
continue;
}
// documentation: 2 conditions, 3x code for word counting
if (!isWordEnd(character)) {
continue;
}
if (character == '\n')
{
line_counter++;
}
if (word_index > 0 && isSentenceEnd(character))
{
sentence_counter++;
}
if (word_index > 0) {
word_counter++;
word[word_index] = '\0';
word_index = 0;
printf("Word %d: %s\n", word_counter, word);
}
}
fprintf(output_file, "Number of lines: %d\n", line_counter);
fprintf(output_file, "Number of words: %d\n", word_counter);
fprintf(output_file, "Number of sentences: %d\n", sentence_counter);
}
Ok here's my buffer lets say:
Hi there how are you doing today? | gap |
So if I want to insert the word 'folks' between you and doing they say I move the gap there first? First what does that mean? Do I copy the characters in that space to a temp buffer, move the empty space (the "cursor") in the buffer there?
Doesn't the rest of the line "doing today?" after the newly inserted "folks", still have to get moved down inside the buffer? So what's the point of the gap buffer then?
I've read some explanations on wiki etc, but still don't quite understand it.
I am learning some new concepts in compilers, and i am thinking to convert my c code to CFG format. How can i achieve it?
C was the first programming language I encountered in my early teens, but I never really learned how to use it. Years later as a professional software developer (currently mostly doing TS) I still didn't feel like I could call myself a "real" programmer before I knew C, so I gave it a go. The result is an opinionated C99 subset called C9 (https://github.com/1jss/C9-lang) intended for beginners just like me. It has been a great learning experience! Feel free to comment if you would have designed it differently and why!
leaning the cirlular double link list
the function del_last have a problem,if i run it.there is an error called :Process finished with exit code 139 (interrupted by signal 11:SIGSEGV)
i asked chatgpt it did'n find out what cased the error.
extremely thanks!
#include <stdio.h>
#include <stdlib.h>
//
// Created by yuan on 24-11-28.
//
struct node
{
struct node *before;
int data;
struct node *after;
};
// struct node* add_to_empty(struct node* tail,int data)
// {
// tail->data=data;
// tail->after=tail;
// tail->before=tail;
// return tail;
// }
// struct node* insert_at_begining(struct node* tail,int data)
// {
// struct node *temp=malloc(sizeof( struct node));
// struct node *head=tail->after;
// temp->data=data;
// temp->before=tail;
// temp->after=head;
// head->before=temp;
// tail->after=temp;
// return tail;
//
// }
// struct node* insert_at_ending(struct node *tail,int data)
// {
// struct node *temp=malloc(sizeof(struct node));
// struct node *head=tail->after;
// temp->data=data;
// tail->after=temp;
// temp->after=head;
// head->before=temp;
// tail->after=temp;
// tail=temp;
// return tail;
// }
// struct node* insert_at_certain_position(struct node *tail,int data,int position)
// {
// struct node *temp=malloc(sizeof( struct node));
// struct node *before=tail;
// struct node *afterr=tail->after;;
// temp->data=data;
// while (position!=1)
// {
// before=afterr;
// afterr=afterr->after;
// position--;
// }
// before->after=temp;
// temp->after=afterr;
// afterr->before=temp;
// temp->before=before;
//
// return tail;
// }
struct node* del_last(struct node* tail)
{
struct node *before=tail->before;
struct node *after=tail->after;
before->after=after;
after->before=before;
tail=before;
free(tail);
return before;
}
// struct node* del_first(struct node* tail)
// {
// struct node *head = tail->after;
//
//
// tail->after=head->after;
// head->after->before=tail;
// free(head);
// return tail;
// }
// struct node* del_at_certain_positio(struct node* tail,int position){}
int main()
{
struct node *tail=malloc(sizeof(struct node));
// tail =add_to_empty(tail,7);
// tail=insert_at_begining(tail,6);
// tail=insert_at_ending(tail,8);
// tail=insert_at_ending(tail,9);
// tail=insert_at_certain_position(tail,5,3);
// tail=del_first(tail);
tail=del_last(tail);
// if (tail != NULL)
// {
// struct node *temp=tail->after;
// do{
// printf("%d",temp->data);
// temp=temp->after;
// } while (temp!=tail->after);
// }
return 0;
}
So, I took some Stack Overflow advice and ran the following command to get my embedded compiler to tell me a little about itself:
echo | arm-none-eabi-gcc -xc -E -v -
And in all of that output, one line was output twice:
COLLECT_GCC_OPTIONS='-E' '-v' '-mcpu=arm7tdmi' '-mfloat-abi=soft' '-marm' '-mlibarch=armv4t' '-march=armv4t'
The second time, it was the last line vomitted up before the program exitted. The first time, the next line after starts with a space, like maybe this was a continuation of it. Though when copy-pasted into a text editor to reformat some of the data, it's clearly a line of its own:
/usr/lib/gcc/arm-none-eabi/14.1.0/cc1 -E -quiet -v -D__USES_INITFINI__ - -mcpu=arm7tdmi -mfloat-abi=soft -marm -mlibarch=armv4t -march=armv4t -dumpbase -
Now, I don't reckon duplicated output for an info dump like this is a cause for alarm. I'm just trying to understand all of the information my toolchain is giving me.
Hey C community, i just started to learn C from the "C programming Language" by Kernighan and Ritchie and there is this exercise to convert first from F to C degrees and now my second exercise is to do it other way around C to F degrees. I changed the variable names and the formula in while loop and the output seems a bit off to me.
my code:
#include <stdio.h>
int
main(){
float
fahr, celsius;
int
lower, upper, step;
lower = 0;
upper = 300;
step = 20;
celsius = lower;
while (celsius <= upper) {
celsius = ((fahr-32) * 5 / 9);
printf("%3.0f %6.1f\n", celsius, fahr);
fahr = fahr + step;
}
}
Output
-18 0.0
-7 20.0
4 40.0
16 60.0
27 80.0
38 100.0
49 120.0
60 140.0
71 160.0
82 180.0
93 200.0
104 220.0
116 240.0
127 260.0
138 280.0
149 300.0
160 320.0
171 340.0
182 360.0
193 380.0
204 400.0
216 420.0
227 440.0
238 460.0
249 480.0
260 500.0
271 520.0
282 540.0
293 560.0
304 580.0
[1] + Done "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-4p5i5may.wao" 1>"/tmp/Microsoft-MIEngine-Out-ga1xumhw.zkh"
This isn't right - right?! o.0 i just googled the -18Cs in the Fahr's and google gave me -40'F WTF
Hi,
I was writing a program and the most annoying thing kept happening for which I couldn't understand the reason; some kind of undefined behavior. I had a separate function, which returned a pointer, to the value of a function, which was then referenced in main. In simple form, think
int *Ihatefunctionsandpointers()
{
return * painintheass;
}
int main(){
int *pointer=Ihatefunctionsandpointers().
return 0;
}
This is a very simple version of what I did in the actual chunk of code below. I suspect that I was getting garbage values because the pointer of main was pointing to some reference in memory that was out of scope. My reasoning being that when I ran an unrelated function, my data would get scrambled, but the data would look ok, when I commented said function out. Further, when I did strcpy(pointer, Ihatefunctionsandpointers(), sizeof()),
the code seems to work correctly. Can someone confirm if a pointer to an out of scope function is dangerous? I thought because the memory was being pointed to, it was being preserved, but I think I was wrong. For reference, my program will tell how many days will lapse before another holiday. I suspect the issue was between main()
and timeformat *setdays(const timeformat *fcurrenttime)
;. My code is below.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#define HDAY .tm_mday
#define HMONTH .tm_mon
typedef struct tm timeformat;
bool Isleap(int year);
int Numberdaysinmonth(int year, int month);
timeformat *setdays(const timeformat *fcurrenttime);
int diffdates(int monthone, int dayone, int monthtwo, int daytwo, int year);
int finddate(const int year, const int month,const int day,const int daycycles);
int dayofweekcalc(int y, int m, int d);
enum IMPDAYS{
Christmas=0, Julyfourth=1, Laborday=2, NewYears=3, Memorialday=4, Thanksgiving=5, maxhdays=6,
};
enum MONTHS
{
Jan=0, Feb=1, Mar=2, Apr=3, May=4, Jun=5, Jul=6, Aug=7, Sept=8, Oct=9, Nov=10, Dec=11, maxmonth=12,
};
enum days
{
Sun=0, Mon=1, Tue=2, Wed=3, Thu=4, Fri=5, Sat=6,
};
void printinfo(const timeformat * const fcurrenttime, const timeformat * const fholidays)
{
char *Holidaytext[]={
[Christmas]={"Christmas"},
[Julyfourth]={"Julyfourth"},
[NewYears]={"NewYears"},
[Thanksgiving]={"Thanksgiving"},
[Laborday]={"Laborday"},
[Memorialday]={"Memorialday"},};
printf("%d\n", diffdates(11, 26, 12, 25, 2024));
printf("%d", diffdates(fcurrenttime->tm_mon, fcurrenttime->tm_mday, fholidays->tm_mon, fholidays->tm_mday, fcurrenttime->tm_year));
}
int main()
{
time_t rawtime;
timeformat *currenttime;
time(&rawtime);
currenttime=localtime(&rawtime);
timeformat *holidays=malloc(sizeof(timeformat)*maxhdays+1);
memcpy(holidays, setdays(currenttime), sizeof(timeformat)*maxhdays);
printinfo(currenttime, holidays);
}
bool Isleap(int year)
{
if(year%4==0 && year%100!=0)
{
return 1;
}
if(year%400==0)return 1;
return 0;
}
int Numberdaysinmonth(const int year, const int month)
{
assert(month<12);
int daysinmonth[]={[Jan]=31, [Feb]=28, [Mar]=31, [Apr]=30, [May]=31, [Jun]=30, [Jul]=31, [Aug]=31, [Sept]=30, [Oct]=31, [Nov]=30, [Dec]=31, [13]=-1};
if(month==1 && Isleap(year)) return *(daysinmonth+month)+1;
return *(daysinmonth+month);
}
timeformat *setdays(const timeformat * const fcurrenttime)
{
timeformat fHolidays[maxhdays]=
{
[Christmas]={HDAY=25, HMONTH=Dec},
[Julyfourth]={HDAY=4, HMONTH=Jul},
[NewYears]={HDAY=1, HMONTH=Jan},
[Thanksgiving]={HDAY=finddate(fcurrenttime->tm_year, Nov, Thu, 4), HMONTH=11},
[Laborday]={HDAY=finddate(fcurrenttime->tm_year, Sept, Mon, 1)},
[Memorialday]={HDAY=finddate(fcurrenttime->tm_year, May, Mon, 1)},
};
return fHolidays;
}
int diffdates(const int monthone,const int dayone, const int monthtwo, const int daytwo, const int year)
{
assert(monthone<12 && monthtwo<12);
assert(dayone>0 && monthone>=0);
if(monthone==monthtwo)return daytwo-dayone;
int difference=0;
difference+=Numberdaysinmonth(year, monthone)-(dayone);
difference+=(daytwo);
for(int currmonth=monthone+1;currmonth<monthtwo; currmonth++)
{
difference+=Numberdaysinmonth(year, currmonth);
}
return difference;
}
int finddate(const int year, const int month,const int day,const int daycycles)
{
int fdaysinmonth=Numberdaysinmonth(year, month);
int daycount=0;
for(int currday=1; currday<fdaysinmonth; currday++)
{
if(dayofweekcalc(year, month, currday)==day)daycount++;
if(daycycles==daycount) return currday;
}
return -1;
}
int dayofweekcalc(int y, int m, int d)
{
int c=y/100;
y=y-100*c;
int daycalc= ((d+((2.6*m)-.2)+y+(y/4)+(c/4)-(2*c)));
return daycalc%7;
}
I'm having fun with ncurses and figuring out how to do a very simple text editor on Slackware linux.
I'm doing it the hard way though cause I like the challenges!
No linked lists or individual lines but am putting all entered characters in one long contiguous array and using various routines to move stuff around, delete and insert etc.
That's what I like most about programming is the challenges in coming up with algorithms for all the little details.
I was fooling around with BACKSPACE and having to delete characters and move higher characters lower etc when using backspace last night. Lots of fun!
Basically I want it to mimic a VERY simple vim but without 99% of the features of course lol!
I was thinking though today about how everything is normally stored in memory with something like an editor.
Are individual lines stored as linked lists and info about each lines length etc, stored in each structure, so that lines can be manipulated and deleted, inserted and moved around etc?
I know nothing about the various types of buffers, like gap buffers etc that I just heard of tonight reading about them.
I'd rather NOT know about them yet though and just figure out things the difficult way, to see why they came about etc.
So last night I was working on a function that moved to the proper element in this single array when the user uses the up and down arrows.
For example, if a user is on the second line and let's say character 4 and presses the up arrow, the algorithm figures out the proper buffer[i] to move to and of course ncurses does the cursor movement using x and y.
But let's say we have a line of 100 characters and we're on character 80 and the above line is only 12 characters long. Then a press of the up arrow will put the cursor at the end of the 12 character line, since it doesn't have 80 characters etc.
Also, if a user is on the top line and presses the up arrow the function returns NULL, since there is no line above.
Or we could have various length lines and a user is continuously pressing the up or down arrow and each line must be compared to the previous line to see where the cursor goes etc.
So I've come up with an algorithm that scans for the first newline moving backwards from the current character and then scans to either the start of the buffer or the next newline and will then be at the start of the line above where the cursor will move.
Then the character offset of the previous line where we were before the up arrow press has to be compared to the new lines length etc.
Anyways, this is all a hobby for me, but it keeps me busy!