4. Array (2) Advanced Applications and Characters and Character Arrays
1. Array-table-driven method-bool type
Table-driven method is also called table-driven and table-driven method. “Table” is a very useful data structure that is discussed in almost all data structure textbooks. The table-driven approach is a method that allows you to look up information in a table without having to use a lot of logical statements (if or case) to find it.
How can we calculate the number of days in a certain month of a certain year? The stupider way is to use if and switch statements to perform multiple judgments
-
Dumb way to redundantly
int iGetMonthDays(int iMonth) { int iDays; if(1 == iMonth) {iDays = 31;} else if(2 == iMonth) {iDays = 28;} else if(3 == iMonth) {iDays = 31;} else if(4 == iMonth) {iDays = 30;} else if(5 == iMonth) {iDays = 31;} else if(6 == iMonth) {iDays = 30;} else if(7 == iMonth) {iDays = 31;} else if(8 == iMonth) {iDays = 31;} else if(9 == iMonth) {iDays = 30;} else if(10 == iMonth) {iDays = 31 ;} else if(11 == iMonth) {iDays = 30;} else if(12 == iMonth) {iDays = 31;} return iDays; }
This leads to what I want to explain, table-driven solution!
#include<stdio.h> #include<stdbool.h> //The header file that the bool data type must include int getdays(int,int); bool is_leapyear(int); int main() {<!-- --> int month = 0; int year = 0; scanf("%d %d", & amp;month, & amp;year); printf("%d", getdays(month-1, year)); return 0; } int getdays(int month, int year) {<!-- --> int months[12] = {<!-- --> 31,is_leapyear(year) ? 29: 28 ,31,30,31,30,31,31,30,31,30,31 }; return months[month]; } bool is_leapyear(int year) {<!-- --> if ((0 == year % 4 & amp; & amp; year % 100 != 0) || (0 == year % 400)) return true; else return false; }
What if we want to be more streamlined?
#include<stdio.h> #include<stdbool.h> int getdays(int,int); int main() {<!-- --> int month = 0; int year = 0; scanf("%d %d", & amp;month, & amp;year); printf("%d", getdays(month-1, year)); return 0; } int getdays(int month, int year) {<!-- --> int months[12] = {<!-- --> 31,(false == year % 4 & amp; & amp; year % 100 != true) || (0 == year % 400) ? 29: 28 ,31,30,31,30,31,31,30,31,30,31}; return months[month]; }
Detailed explanation:
#include<stdio.h> #include<stdbool.h> //The header file that the bool data type must include int getdays(int,int); bool is_leapyear(int); int main() {<!-- --> int month = 0; int year = 0;//table driven method scanf("%d %d", & amp;month, & amp;year); printf("%d", getdays(month-1, year)); return 0; }//Returns the number of days in each month, relying on the is_leapyear function int getdays(int month, int year) {<!-- -->//Perform operations on array elements, omitting a large number of conditional statements int months[12] = {<!-- --> 31,is_leapyear(year) ? 29: 28 ,31,30,31,30,31,31,30,31,30,31 }; return months[month]; } bool is_leapyear(int year)//determine whether it is a leap year {<!-- --> if ((0 == year % 4 & amp; & amp; year % 100 != 0) || (0 == year % 400)) return true; else return false; }
2. Enumeration
–Although this is an independent section, it is similar to arrays, so I will put it here.
Enumeration actually means omitting cumbersome macro definitions and assigning values to enumerated elements at once. Enumeration types are very commonly used.
An enumerated type in C is a user-defined data type that allows programmers to assign easy-to-remember names to integer values to improve code readability and maintainability. An enumeration type is defined after the enum
keyword and is surrounded by a pair of curly braces, inside which is a series of named integer constants.
The following is the basic syntax for enumeration types:
enum enumeration name {<!-- --> Name 1, Name 2, Name 3, // ... other names };
Each name (also called an enumerator) corresponds to an integer value. By default, the first enumerator has a value of 0
, and subsequent enumerators have values that are incremented. You can also manually specify specific values for the enumerator:
enum enumeration name {<!-- --> Name1 = 10, Name 2, // value is 11 Name 3 = 20, Name 4, // value is 21 // ... other names };
In this example, Name1
is assigned the value 10
, and Name2
has no value specified, so its value is Name1< Add
1
to the value of /code>, which is 11
. Name3
is assigned the value 20
, and Name4
is 21
.
Enumeration types are often used to represent a set of related constant values, such as status codes, error codes, or specific mode selections. Using enumeration types can be more clear and organized than using #define
or ordinary constant definitions.
In actual use, you can use enumeration variables just like ordinary integer types, for example:
enum day {<!-- -->SUN, MON, TUE, WED, THU, FRI, SAT}; int main() {<!-- --> enum day today = WED; if (today == WED) {<!-- --> // perform some operations } return 0; }
In this example, we define an enumeration type named day
, which contains the seven days of the week, and then we declare a variable of type enum day
today
, and assign the value to WED
. In the if
statement, we can directly use the enumeration value for comparison.
There are several advantages to using enumeration types:
- Code is easier to understand and maintain because enum values are more descriptive than bare integers.
- Enumeration types are type-checked by the compiler, which helps reduce errors.
- Enumerations can be displayed more clearly with the debugger for easier debugging.
In summary, an enumeration is a concise and powerful data structure in C language, suitable for managing a set of named integer constants.
3. String
- A string of characters ending with 0 (positive number 0),
0 or \0’
are the same, but different from0’
- 0 marks the introduction of the string, but it is not part of the string
- Zero should not be included when calculating string length
- Strings exist in the form of arrays and are accessed in the form of arrays or pointers, more in the form of pointers
- The header file
string.h
has many functions for processing strings.
Important points:
- Strings in C language exist in the form of character arrays
- Operators cannot be used on strings
- Strings can be traversed through arrays
- The only special thing is that string literals can be used to initialize character arrays
- If two strings are written consecutively, C language will help us connect them.
3.1String constants
char* s = "hello,world";
- s is a pointer, initialized to point to a string constant
- Because of the location of this constant, s is actually
const char * s
. However, due to historical reasons, the compiler accepts writing without const. - But trying to write/modify the string pointed to by s will lead to serious consequences.
- If you need to modify the string, you should use an array: char s[] = “hello,world”;
char line[10] = "hello"; line[1] = 'b'; printf("%s",line);
Let me give an example: char *s1 = “hello”; char *s2 = “hello”;
So pointer or array?
Basic idea: If you want to construct a string → array; if you want to process a string → pointer;
For arrays:
- This string is right here
- As local variable space is automatically reclaimed
For pointers:
- I don’t know where this string is
- Process parameters and dynamically allocate space
Final things to remember:
- A string can express the form of char, but char is not necessarily a string. The original intention is a pointer to a character, which may point to an array of characters (just like int*)
- Only when the character array pointed to by char* has a trailing 0, can it be said that it points to a string.
3.2 String array
int main() {<!-- --> //char[10]; a[0] is equivalent to a char[10] //a[0] is equivalent to cha* char a[][10] = {<!-- --> "hello", "world",}; char *b[10] = {<!-- --> "hello", "world", }; return 0; }//The output results are the same
So what is the difference between these two ways of writing?
-
main function parameters
*1. Under what circumstances should int main(int argc, char argv[]) be used?
We need to interact with the program. You know, during the running of the program, you can use the scanf function to input arrays, characters, and strings for the program to process.
So can you bring parameters to the program when it starts (), instead of typing things into the program during operation? At this time, you need to use the main function with parameters (int argc, char *argv[]).
You have probably used the ping command to ping an IP address, for example: ping 192.168.0.1
In fact, the ping here is an exe program, and “192.168.0.1” is a string, which is the parameter we pass to the program.
Therefore, when you need the program to start with parameters, use int main(int argc, char *argv[]).
2. How to use argc and argv parameters.
You may think that argc and argv are parameters passed to the main function. Who passed this parameter? Isn’t the main function already the entry function? Are there other functions that call the main function?
argc and argv are what you pass to the program through the command line window.
Can you guess what the result of the following program is?
#include
int main(int argc , char *argv[]) { printf("argc = %d\
", argc); printf("%s\
", *argv); }We compile and run, and the results are as follows. Have you noticed that *argv is a string, and the content of the string is the exe program file name (including its full path).
argc = 1, what does this mean? It means that the command line has a string. This string is “D\test\main_arg_argv.exe”, which is our program name.
You might be thinking:
(1) How to pass a string to the program through the command line?
(2) How does the program obtain the passed string?
the answer is:
(1) Pass the string to the program in this format:
Program name.exe string 1 string 2 string 3… string n
When executing an exe program, you can add any number of strings after the .exe name. Separate each string with spaces.
(2) In the main function, receive strings one by one through a loop.
for example:
Let’s make a program like this:
Require:
If a string passed is equal to “Aa”, “A for apple” will be printed; if a string passed is equal to “Bb”, “B for ball” will be printed; if a string passed is equal to “Cc”, ” C for ball”, if a string passed is equal to “Dd”, it will output “D for dog”.
First the code:
#include <stdio.h> #include <string.h> int main(int argc, int *argv[]) {<!-- --> printf("argc = %d\ ", argc); argv + + ; while (*argv){<!-- --> if (strcmp(*argv, "Aa") == 0){<!-- --> argv + + ; printf("A for apple\ "); }else if (strcmp(*argv, "Bb") == 0){<!-- --> argv + + ; printf("B for ball\ "); }else if (strcmp(*argv, "Cc") == 0){<!-- --> argv + + ; printf("C for cat\ "); }else if (strcmp(*argv, "Dd") == 0){<!-- --> printf("in d\ "); argv + + ; printf("D for dog\ "); } } }
Note that at this time, we cannot run the program directly in the editor, because there are no parameters for automatic operation.
Click the compile button in the picture below. Then enter the folder where the source file is located: D:\test. You can see that a file named main_argc_argv.exe is generated. This is the executable file generated by compilation, commonly known as “program/software”.
D:\test\main_argc_argv.exe
So how does it work?
Open the command line, select the .exe file with the left mouse button, and drag it to the cmd window:
Then add the string we want to add at the end. Add “Cc” and “Aa” here
Then, press Enter to run.
As we expected, when we type parameters on the command line, Cc is in front of Aa, so “C for cat” is printed first, and then “A for apple” is printed.
Note: argc here is 3, what does it mean?
As we said before, when arrgc=1, it means that the command line has only one string, which is the program name “D\test\main_arg_argv.exe”.
3 means that the command line has three strings, namely: program name “D\test\main_arg_argv.exe”, “Cc” and “Aa”.
Now you should understand how to use the parameters in the main function.
3. Summary
When you need the program to start with parameters, use int main(int argc, char *argv[]).
4. Use of string functions
4.1 strcmp is used to compare two strings
- Compares two strings and returns:
- 0: s1==s2; 1: s1>s2; -1: s1
Arrays cannot be compared directly because their addresses are different. Why does printf return 0? Think about the printf mentioned before that will return the number of bytes of the number of parameters! , because it cannot be compared, it is always false!
4.2strcpy
- Function prototype: char*(charrestrict det, const charrestrict src);
- Copy the latter string to the previous character, restrict indicates that the two strings cannot overlap
- Returns the copied character dst, this is to chain the code
Usage: char det = (char)malloc(strlen(src) + 1);
strcpy(dst,src);
4.3 Finding characters in strings
5. Dynamic memory allocation
#include<stdio.h> #include<stdlib.h>//Used to export the malloc function int main_9() {<!-- --> int number; int* a; int i; scanf("%d", & amp;number); // int a[number]; a = (int*)malloc(number * sizeof(int));//Use a as an array (int*) type conversion, because malloc is followed by void for (i = 0; i < number; i + + ) {<!-- --> //Treat as an array. scanf("%d", & amp;a[i]); } for (i = number - 1; i >= 0; i--) {<!-- --> printf("%d", a[i]); } free(a); //Return the space. You can only return the first address of the applied space. \t return 0; } int main_9_2(void)//Detect allocated space size {<!-- --> void* p; int cnt = 0; while ((p = malloc(100 * 1024 * 1024))) {<!-- --> cnt + + ; } printf("?0MB space allocated", cnt); return 0; }
Frequently Asked Questions: Is it free after applying → Memory gradually decreases after long-term operation
Novice: Forgot; Veteran: Can’t find the right time to free; Free after free; Go to free directly after the address has changed;
int main(void) {<!-- --> int i; void* p; int cnt = 0; p = malloc(100 * 102400); p + + ; free(p);} // The address of p has changed, and free here is an invalid code
We use free(NULL) to prevent the program from doing anything! This is also good practice.
We must remember to add free!
6. Input and output of single characters
6.1 putchar()
- Function prototype: int putchar(int c);
- Write a character to standard output
- Returns how many characters have been written. EOF (-1) indicates writing failure.
In the win system environment, enter: CTRL + Z
to indicate input failure.
//Common models: while((ch = getchar())!=EOF){<!-- -->//This returns the EOF program to end the loop putchar(ch); }
The reason is that there are input and output buffers.
6.2getchar()
- Can only read a single character
- Function prototype: int getchar(void);
- The return type is int to return EOF (-1)
In the win system environment, enter: CTRL + Z
to indicate input failure.
7. String input and output
In C language, string input is usually implemented through the standard input function. The most common methods are to use the scanf
function or the gets
function. However, it should be noted that using these functions requires careful handling of buffer overflow issues. Here are some common string input methods:
-
Using the
scanf
function:
Thescanf
function can be used to read formatted input from standard input (usually the keyboard). When used with strings, it is typically used with the%s
formatting identifier. For example:char str[100]; printf("Enter a string: "); scanf("?s", str); // Note that ?s is used here to avoid buffer overflow
However, it should be noted that scanf cannot handle line breaks, spaces, tabs, etc. Therefore, when using scanf, you must ensure that there are no line breaks, spaces, tabs, etc. in the string.
-
Using the
gets
function:
Thegets
function reads a line of text until a newline character is encountered. However,gets
is unsafe because it does not check the size of the target buffer and can easily cause buffer overflow. Therefore, it has been deprecated in the latest C standard. If you still want to use it, the code is as follows:char str[100]; printf("Enter a string: "); gets(str); // Not recommended because of security risks
-
Using the
fgets
function:
As a safe alternative togets
, thefgets
function reads a line from a file or standard input until a newline character is encountered or a specified number of characters is reached. It checks the buffer size to avoid overflow. For example:char str[100]; printf("Enter a string: "); fgets(str, sizeof(str), stdin); // safe, recommended
In actual programming, it is recommended to use the scanf
(remember to limit the input length) or the fgets
function, because they are safer and can prevent buffer overflow problems.
These three functions will automatically complete '\0'
at the end of the string, which is NULL
In practice, gets and puts are often used together.
puts
function
The puts
function is used to output a string to standard output (usually the screen), and automatically adds a newline character after the output string.
cCopy code char str[] = "Hello, world!"; puts(str); // Output the string str and add a newline character at the end
The puts
function is relatively safe because it does not involve writing to a buffer. It simply outputs an existing string and adds a newline character at the end.
To sum up, although gets
and puts
are paired functions, due to gets
security risks, it is recommended to use fgets
instead of gets
, and < strong>puts
can continue to be used to output strings.