This commit is contained in:
许大仙 2024-08-01 10:00:11 +08:00
commit c7b88451d5
421 changed files with 12265 additions and 0 deletions

1
.env.development Normal file
View File

@ -0,0 +1 @@
VITE_BASE_URL='./'

1
.env.production Normal file
View File

@ -0,0 +1 @@
VITE_BASE_URL='/c/'

31
.github/workflows/deploy.yaml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Deploy
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: "拉取代码"
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: "设置node.js的版本"
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: "安装依赖"
run: |
npm install
- name: "打包"
run: |
npm run docs:build
- name: "部署"
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/.vitepress/dist

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
node_modules
cache
dist
.idea
.vscode

674
LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# c/c++
c/c++ 学科

View File

@ -0,0 +1,63 @@
import { defineConfig } from 'vitepress'
import { nav } from './navbar'
import sidebar from './sidebar'
import dayjs from 'dayjs'
import { loadEnv } from 'vitepress'
const { VITE_BASE_URL } = loadEnv(process.env.NODE_ENV == undefined ? "" : process.env.NODE_ENV, process.cwd())
console.log('VITE_BASE_URL', process.env.NODE_ENV, VITE_BASE_URL)
// https://vitepress.dev/reference/site-config
export default defineConfig({
lang: 'zh-CN', // html 标签的 language
title: "许大仙", // 标题
titleTemplate: "Hi终于等到你",
description: "许大仙前端、Java、大数据、云原生",
head: [ // favicon.ico 图标等
['link', { rel: "shortcut icon", href: `${VITE_BASE_URL}/logo.svg` }],
['meta', { name: "viewport", content: "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,shrink-to-fit=no" }],
['meta', { name: "keywords", content: "许大仙,许大仙的博客" }],
],
base: VITE_BASE_URL,
lastUpdated: true, // 上次更新
vite: {
build: {
chunkSizeWarningLimit: 1600
},
plugins: [],
server: {
port: 18088
}
},
markdown: { // markdown 配置
math: true,
lineNumbers: true, // 行号显示
},
themeConfig: {// 主题设置
lastUpdatedText: '上次更新', // 上次更新显示文本
returnToTopLabel: '返回顶部', // 更改手机端菜单文字显示
search: { // 本地搜索
provider: 'local'
},
logo: '/logo.svg', // 左上角logo
nav: nav, // 导航
sidebar: sidebar, // 侧边栏
socialLinks: [ // 社交链接
{ icon: 'github', link: 'https://github.com/Aurorxa' }
],
docFooter: { // 自定义上下页名
prev: '上一篇', next: '下一篇'
},
footer: { // 页脚
message: 'Released under the MIT License.',
copyright: `Copyright © ${dayjs().format("YYYY")} 许大仙`
},
outline: { // 大纲显示 1-6 级标题
level: [1, 6],
label: '目录'
},
//大纲顶部标题
outlineTitle: '当前页大纲',
}
})

View File

@ -0,0 +1,17 @@
import { DefaultTheme } from 'vitepress'
export const nav: DefaultTheme.NavItem[] = [
{ text: '首页', link: 'https://aexiar.github.io/' },
{ text: '计组6件套', link: 'https://aexiar.github.io/coa6/notes/' },
{
text: '编程语言', items: [
{ text: 'c/c++', link: '/notes/' },
{ text: '前端', link: 'https://aexiar.github.io/web-design/notes/' },
{ text: 'Java', link: 'https://aexiar.github.io/java/notes/' },
{ text: '大数据', link: 'https://aexiar.github.io/big-data/notes/' },
{ text: '云原生', link: 'https://aexiar.github.io/linux/notes/' },
{ text: 'Go', link: 'https://aexiar.github.io/go/notes/' },
{ text: 'Python', link: 'https://aexiar.github.io/python/notes/' },
]
},
{ text: '开源软件', link: 'https://aexiar.github.io/open-software/notes/' },
]

View File

@ -0,0 +1,70 @@
import { DefaultTheme } from 'vitepress'
import { commonDirectoryName } from '../utils/constant'
export const sidebar: DefaultTheme.Sidebar = {
'/notes/': [
{
text: 'C 语言基础',
collapsed: true,
items: [
{ text: 'C 语言入门', link: `/notes/01_c-basic/01_${commonDirectoryName}/` },
{ text: '变量和进制', link: `/notes/01_c-basic/02_${commonDirectoryName}/` },
{ text: '数据类型和运算符', link: `/notes/01_c-basic/03_${commonDirectoryName}/` },
{ text: '流程控制', link: `/notes/01_c-basic/04_${commonDirectoryName}/` },
{ text: '数组', link: `/notes/01_c-basic/05_${commonDirectoryName}/` },
{ text: '指针', link: `/notes/01_c-basic/06_${commonDirectoryName}/` },
{ text: '函数', link: `/notes/01_c-basic/07_${commonDirectoryName}/` },
{ text: '预处理器', link: `/notes/01_c-basic/08_${commonDirectoryName}/` },
{ text: '自定义数据类型', link: `/notes/01_c-basic/09_${commonDirectoryName}/` },
{ text: '字符串和时间', link: `/notes/01_c-basic/10_${commonDirectoryName}/` },
{ text: '内存管理', link: `/notes/01_c-basic/11_${commonDirectoryName}/` },
{ text: '文件操作', link: `/notes/01_c-basic/12_${commonDirectoryName}/` },
{ text: '调试工具和调试技巧gdb和make', link: `/notes/01_c-basic/13_${commonDirectoryName}/` },
{ text: '常用库函数', link: `/notes/01_c-basic/14_${commonDirectoryName}/` },
]
},
{
text: 'C 语言高级',
collapsed: true,
items: [
]
},
{
text: 'Linux',
collapsed: true,
items: [
{ text: 'Linux 初识和安装', link: `/notes/03_linux/01_${commonDirectoryName}/` },
]
},
{
text: 'C++ 核心编程',
collapsed: true,
items: [
]
},
{
text: 'C++ 标准库',
collapsed: true,
items: [
]
},
{
text: 'QT 桌面开发',
collapsed: true,
items: [
]
},
{
text: 'Linux 高并发服务器开发',
collapsed: true,
items: [
]
}
],
}
export default sidebar

View File

@ -0,0 +1,71 @@
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import mediumZoom from 'medium-zoom'
import { onMounted, watch, nextTick } from 'vue'
import giscusTalk from 'vitepress-plugin-comment-with-giscus'
import { useData, useRoute } from 'vitepress'
import './style/index.css'
export default {
extends: DefaultTheme,
setup() {
// Get frontmatter and route
const { frontmatter } = useData()
const route = useRoute()
const initZoom = () => {
// mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' }); // 默认
mediumZoom('.main img', { background: 'var(--vp-c-bg)' }) // 不显式添加{data-zoomable}的情况下为所有图像启用此功能
};
onMounted(() => {
initZoom()
// 禁止 ios 缩放屏幕
document.addEventListener('gesturestart', function (event) {
event.preventDefault()
})
// 禁止移动端IOS双击页面变大
let touchTime = 0
document.addEventListener('touchstart', function (event) {
if (event.touches.length > 1) {
event.preventDefault()
}
})
document.addEventListener(
'touchend',
function (event) {
//记录当前点击的时间与下一次时间的间隔
const nowTime = new Date()
if (nowTime.getTime() - touchTime <= 300) {
event.preventDefault()
}
touchTime = nowTime.getTime()
},
false
);
})
watch(
() => route.path,
() => nextTick(() => initZoom())
);
// giscus配置
giscusTalk({
repo: 'Aexiar/Aexiar.github.io', //仓库
repoId: 'R_kgDOK820xg', //仓库ID
category: 'Announcements', // 讨论分类
categoryId: 'DIC_kwDOK820xs4Cb8sS', //讨论分类ID
mapping: 'pathname',
inputPosition: 'bottom',
lang: 'zh-CN',
},
{
frontmatter, route
},
//默认值为true表示已启用此参数可以忽略
//如果为false则表示未启用
//您可以使用“comment:true”序言在页面上单独启用它
true
)
}
}

View File

@ -0,0 +1 @@
@import './var.css';

View File

@ -0,0 +1,19 @@
.medium-zoom-overlay {
z-index: 20;
}
.medium-zoom-image {
z-index: 9999 !important;/* 给的值是21但是实测盖不住直接999 */
}
/* 禁止双指缩放 */
body, html {
touch-action: manipulation;
-webkit-touch-callout: none;
-ms-touch-action: manipulation;
}
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff);
}

View File

@ -0,0 +1 @@
export const commonDirectoryName: string = "xdx"

69
docs/index.md Normal file
View File

@ -0,0 +1,69 @@
---
# 官方文档相关配置https://vitepress.dev/reference/default-theme-layout
layout: home
home: true
# 官方文档相关配置https://vitepress.dev/reference/default-theme-home-page
title: 许大仙的博客
titleTemplate: Hi终于等到你
editLink: true
lastUpdated: true
head:
- - meta
- name: description
content: 许大仙前端、Java、大数据、云原生
- - meta
- name: keywords
content: 许大仙,许大仙的博客
hero:
name: "许大仙同学"
text: ""
tagline: "『这个世纪疯狂,没人性,腐败;你却一直清醒,温柔,一尘不染。教育商店。』"
# 按钮相关
actions:
- theme: brand
text: "首页"
link: "https://aexiar.github.io"
- theme: alt
text: "计组6件套"
link: "https://aexiar.github.io/coa6/notes/"
- theme: alt
text: "c/c++"
link: "/notes/"
- theme: alt
text: "前端"
link: "https://aexiar.github.io/web-design/notes/"
- theme: alt
text: "Java"
link: "https://aexiar.github.io/java/notes/"
- theme: alt
text: "大数据"
link: "https://aexiar.github.io/big-data/notes/"
- theme: alt
text: "云原生"
link: "https://aexiar.github.io/linux/notes/"
- theme: alt
text: "Go"
link: "https://aexiar.github.io/go/notes/"
- theme: alt
text: "Python"
link: "https://aexiar.github.io/python/notes/"
- theme: alt
text: "开源软件"
link: "https://aexiar.github.io/open-software/notes/"
# 按钮下方的描述
features:
- title: "学习思路"
details: "学习思路就这么几条:模仿、遍历、分治、动态规划、……"
- title: "学习手法"
details: "学习手法就这么几种:缓存、索引、信号/事件、回调/消息循环/dispatcher、……"
- title: "注意事项"
details: "注意事项就这么几点:边界值、等价类、数据完整性原子性、死锁、空转、……"
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -0,0 +1,1830 @@
# 第一章:计算机组成原理
## 1.1 计算机系统
* 计算机Computer俗称`"电脑"`,是一种能够接收和存储信息,并按照存储在其内部的程序对海量的数据进行自动、高速的处理,然后将处理结果输出的现代化智能电子设备。
* 计算机有很多形式,如:台式电脑、笔记本电脑、智能手机、平板电脑等,还有生产环境中提供重要业务支撑的各种服务器。
![](./assets/1.jpg)
* 一个完整的`计算机系统`由`硬件Hardware系统`和`软件Software系统`两大部分组成,即:
![](./assets/2.png)
## 1.2 冯·诺依曼体系结构
* `冯·诺依曼`是一位多才多艺的科学家,他在数学、物理学、计算机科学、经济学等领域都有杰出的贡献。
![](./assets/3.jpg)
* `冯·诺依曼`的主要成就:
- 在计算机科学领域的最著名贡献是提出了`冯·诺依曼`体系结构1946 年),这是`现代计算机设计的基础`。
- 促进了计算机的可编程性和通用性,使得计算机能够执行各种复杂的任务。
- 对核武器设计、自动化控制系统、人工智能等领域的发展产生了重要影响。
- ……
> [!IMPORTANT]
>
> `冯·诺依曼体系结构`是现代计算机(量子计算机除外)设计的`基础`。
* `冯·诺依曼`体系结构的理论要点如下:
- ① **存储程序**`程序指令`和`数据`都存储在计算机的内存中,这使得程序可以在运行时修改。
- ② **二进制逻辑**:所有`数据`和`指令`都以`二进制`形式表示。
- ③ **顺序执行**:指令按照它们在内存中的顺序执行,但可以有条件地改变执行顺序。
- ④ **五大部件**:计算机由`运算器`、`控制器`、`存储器`、`输入设备`和`输出设备`组成。
- ⑤ **指令结构**:指令由操作码和地址码组成,操作码指示要执行的操作,地址码指示操作数的位置。
- ⑥ **中心化控制**计算机的控制单元CPU负责解释和执行指令控制数据流。
![](./assets/4.png)
> [!NOTE]
>
> 上述的组件协同工作,构成了一个完整的计算机系统:
>
> * **运算器**和**控制器**通常被集成在一起组成中央处理器CPU负责数据处理和指令执行。
> * **存储器**保存数据和程序,是计算机运作的基础。
> * **输入设备**和**输出设备**负责与外界的交互,确保用户能够输入信息并接收计算机的处理结果。
## 1.3 各种硬件处理速度和性能优化
* 计算机的性能短板:如果 CPU 有每秒处理 1000 个服务请求的能力,各种总线的负载能力能达到 500 个, 但网卡只能接受 200个请求而硬盘只能负担 150 个的话,那这台服务器得处理能力只能是 150 个请求/ 秒,有 85% 的处理器计算能力浪费了,在计算机系统当中,`硬盘`的读写速率已经成为影响系统性能进一 步提高的瓶颈。
![img](./assets/5.jpg)
* 计算机的各个设备部件的延迟从高到低的排列依次是机械硬盘HDD、固态硬盘SSD、内存、CPU 。
![img](./assets/6.png)
* 从上图中我们可以知道CPU 是最快的,一个时钟周期是 0.3 ns ,内存访问需要 120 ns ,固态硬盘访问需要 50-150 us传统的硬盘访问需要 1-10 ms而网络访问是最慢需要 40 ms 以上。
* 时间的单位换算如下:
```txt
1 秒 = 1000 毫秒,即 1 s = 1000 ms。
1 毫秒 = 1000 微妙,即 1 ms = 1000 us 。
1 微妙 = 1000 纳秒,即 1 us = 1000 ns。
```
* 按照上图,将计算机世界的时间和人类世界的时间进行对比,即:
```txt
如果 CPU 的时钟周期按照 1 秒计算,
那么,内存访问就需要 6 分钟;
那么,固态硬盘就需要 2-6 天;
那么,传统硬盘就需要 1-12 个月;
那么,网络访问就需要 4 年以上。
```
* 所以,对于 CPU 来说,这个世界真的是太慢了!!!
* 其实,中国古代中的文人,通常以`蜉蝣`来表示时间的短暂(和其他生物的寿命比),也是类似的道理,即:
```txt
鹤寿千岁,以极其游,蜉蝣朝生而暮死,尽其乐,盖其旦暮为期,远不过三日尔。
--- 出自 西汉淮南王刘安《淮南子》
```
```txt
寄蜉蝣于天地,渺沧海之一粟。 哀吾生之须臾,羡长江之无穷。
挟飞仙以遨游,抱明月而长终。 知不可乎骤得,托遗响于悲风。
--- 出自 苏轼《赤壁赋》
```
>[!NOTE]
>
>对于`蜉蝣`来说,从早到晚就是一生;而对于我们`人类`而言,却仅仅只是一天。
* 存储器的层次结构CPU 中也有存储器,即:寄存器、高速缓存 L1、L2 和 L3如下所示
![img](./assets/7.png)
>[!NOTE]
>
>上图以层次化的方式,展示了价格信息,揭示了一个真理,即:天下没有免费的午餐(千万不要相信别人会有发财的机会和你共享,人都是自私的,你算个啥?为什么要找你?)
>
>- ① 存储器越往上速度越快,但是价格越来越贵, 越往下速度越慢,但是价格越来越便宜。
>- ② 正是由于计算机各个部件的速度不同,容量不同,价格不同,导致了计算机系统/编程中的各种问题以及相应的解决方案
## 1.4 计算机软件
### 1.4.1 操作系统的来源
* 在上古时期,硬件资源不够丰富,计算机设计的也非常简陋。那个时候,很多应用程序都是直接跑在硬件上的,即:一个计算机只能跑一个应用程序。
![](./assets/8.png)
* 随着技术的发展,硬件越来越丰富,功能也越来越强大,性能也越来越好。这种情况下,如果一台计算机只能跑一个程序,实在是太浪费了。而且,底层硬件不断丰富,应用程序需要对接的硬件也将越来越多,如果每个应用程序都这么干,不显示工作很重复吗?于是,操作系统应运而生了。
![](./assets/9.png)
- 操作系统的功能:
- 硬件驱动。
- 进程管理。
- 内存管理。
- 网络管理。
- 安全管理。
- 文件管理。
* 那么,操作系统的作用,就是这样的,即:
* 对下,管理计算机的硬件资源。
* 对上,提供使用计算机资源的操作方式,有:
* `系统调用`:是一套已经写好的代码接口,应用程序通过调用这些接口来请求操作系统执行特定的硬件操作。它们直接与硬件交互,提供底层功能支持,如:文件操作、进程管理、内存管理等。`开发者`通过系统调用可以实现对底层资源的直接控制,确保程序能够高效、安全地运行。
* `终端命令`:是一种文本命令接口,通过命令行输入各种指令来控制操作系统和软件的行为。终端命令可以执行文件操作、系统配置、网络管理等各种任务。主要针对`开发人员`和`高级用户`,他们通过命令行可以快速、精确地完成各种操作,提高工作效率。
* `图形用户界面`GUI是通过图形元素窗口、图标、按钮等与用户进行交互的界面。供直观、易用的操作方式使用户能够通过鼠标点击、拖拽等简单操作完成复杂任务。主要面向`普通用户`,降低了计算机操作的门槛,提高了用户体验和工作效率。
![](./assets/10.png)
### 1.4.2 用户态和内核态
* 在现代操作系统中,`用户态User Mode`和`内核态Kernel Mode`是两种不同的执行模式,它们对系统资源的访问权限有着本质的区别。这种区分是为了提供一个稳定和安全的运行环境,防止用户程序直接操作硬件设备和关键的系统资源,从而可能引起系统的不稳定或安全问题。
![](./assets/11.png)
- 核态Kernel Mode VS 用户态User Mode
| 类型 | 内核态Kernel Mode | 用户态User Mode |
| :----- | :----------------------------------------------------------- | :----------------------------------------------------------- |
| 权限 | 内核态是操作系统代码运行的模式,拥有访问系统全部资源和执行硬件操作的`最高权限`。在这种模式下,操作系统的核心部分可以直接访问内存、硬件设备控制、管理文件系统和网络通信等。 | 用户态是普通应用程序运行的模式,具有`较低`的系统资源访问权限。在用户态,程序不能直接执行硬件操作,必须通过操作系统提供的接口(即系统调用)来请求服务。 |
| 安全性 | 由于内核态具有如此高的权限,因此只有可信的、经过严格审查的操作系统核心组件才被允许在此模式下运行。这样可以保护系统不被恶意软件破坏。 | 用户态为系统提供了一层保护,确保用户程序不能直接访问关键的系统资源,防止系统崩溃和数据泄露。 |
| 功能 | 内核态提供了`系统调用`的接口,允许用户态程序安全地请求使用操作系统提供的服务,比如:文件操作、网络通信、内存管理等。 | 用户态保证了操作系统的稳定性和安全性,同时也使得多个程序可以在相互隔离的环境中同时运行,避免相互干扰。 |
> [!NOTE]
>
> - ① 操作系统通过用户态和内核态的分离,实现了对系统资源的保护和控制。
> - ② 当用户程序需要进行文件读写、网络通信或其他需要操作系统介入的操作时会发生从用户态到内核态的切换。这通过系统调用System Call实现系统调用是用户程序与操作系统内核通信的桥梁。
> - ③ 执行完毕后,系统从内核态返回用户态,继续执行用户程序。
> - ④ 用户态和内核态的这种分离设计是现代操作系统中实现安全、稳定运行的关键机制之一。
* 示例:
```java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class Demo {
public static void writeFile(String filePath, String content) {
Path path = Paths.get(filePath);
try {
Files.write(path, content.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
int a = 10; // 用户态
int b = 20; // 用户态
int c = a + b; // 用户态
string filePath = "c:/demo.txt"; // 用户态
string txt = a + b + c; // 用户态
writeFile(filePath, a); // 从用户态切换到内核态完成文件写入
System.out.println(a); // 从内核态切换回用户态
System.out.println(b); // 用户态
System.out.println(c); // 用户态
}
}
```
### 1.4.3 ISA、ABI 和 API
- ISA 、ABI 和 API 的参考模型如下:
![](./assets/12.jpg)
* 在底层,硬件模型以指令集架构 ISA 表示该架构定义了处理器、寄存器、存储器和中断管理的指令集。ISA 是硬件和软件之间的接口,对于操作系统 OS 开发人员 System ISA 和直接管理底层硬件的应用程序 User ISA 的开发人员来说非常重要。
> [!NOTE]
>
> - ① ISA 是计算机体系结构中定义的一组指令它规定了处理器能够执行的操作。ISA 包括指令的编码、寄存器的使用、内存访问模式等。不同的处理器可能有不同的 ISA例如x86、ARM、MIPS 等。
> - ② 在设计一个新的操作系统时,开发者需要确保操作系统能够支持特定的 ISA ,以便在特定的硬件上运行。例如:如果操作系统旨在运行在 ARM 架构的处理器上,那么它必须能够理解和执行 ARM ISA 定义的指令集。
- 应用程序二进制接口 ABI 将`操作系统层`与由操作系统管理的`应用程序`和`库`分开。ABI 涵盖了低级数据类型、对齐方式和调用约定等详细信息,并定义了可执行程序的格式。系统调用在此级别定义。此接口允许应用程序和库在实现相同 ABI 的操作系统之间移植。
> [!NOTE]
>
> - ① ABI 是指在二进制级别上应用程序与操作系统、库或应用程序的不同部分之间的接口。它定义了数据类型的大小、布局、对齐方式以及函数调用的约定如参数如何传递、返回值如何处理等。ABI 确保了编译后的二进制文件能够在特定的操作系统和硬件平台上正确地运行。
> - ② 在 windows 上的应用程序的运行格式是:`PE`portable executable格式、`.dll` dynamic link library格式和 `.lib` 格式;而在 Linux 上的应用程序的运行格式是:`ELF`executable and linking format格式、`.so` shared object格式和 `.a` 格式。
> - ③ 在 Linux 中可以通过 `file /bin/ls` 命令查看指定可执行应用程序的 ABI 格式;从而也可以论证,在 Windows 上可以运行的程序,在 Linux 上运行不了。
> - ④ 当开发者在 Linux 系统上编写 C 语言程序并使用特定的编译器GCC编译时编译器会遵循 Linux 平台的 ABI 规范来生成二进制文件。这样,生成的可执行文件就可以在任何遵循相同 ABI 规范的 Linux 系统上运行。
> - ⑤ 如果一个应用程序需要跨平台(操作系统)运行,就需要使用`一套代码,多平台编译`的方式(针对 C 或 C++ 等相同的源代码在不同平台操作系统上使用特定平台的编译器GCC来分别编译成符合自己平台的 ABI 规范的二进制文件。
- 最高级别的抽象由应用程序编程接口 API 表示,它将`应用程序`连接到`库`或`底层操作系统`。
> [!NOTE]
>
> - ① API 是一组预定义的函数、协议和工具用于构建软件和应用程序。API 允许不同的软件系统相互交互它定义了软件组件之间如何相互通信。API 可以是库、框架、协议或服务。
> - ② 在 Web 开发中,开发者可能会使用 JavaScript 的 Fetch API 来与服务器进行通信,获取数据或提交表单。这个 API 提供了一种标准化的方式来发送 HTTP 请求和处理响应,而不需要开发者关心底层的网络协议细节。
### 1.4.4 系统调用System Call和函数库Library Call
* 在现代操作系统中,应用程序都不能直接作用于硬件,而是运行在操作系统之上。
![](./assets/13.png)
- 并且,在上文的图示中,我们也会看到`系统调用System Call`和`函数库Library Call`的身影,如下:
![](./assets/14.png)
![](./assets/15.png)
* 其实,`系统调用System Call`和`函数库Library Call`的区别如下:
| 类型 | 系统调用System Call | 函数库Library Call |
| :------- | :----------------------------------------------------------- | :----------------------------------------------------------- |
| 定义 | 系统调用是操作系统提供给程序员的一组接口,这些接口允许用户空间的程序请求操作系统内核提供的服务,比如文件操作、进程控制、通信和内存管理等。 | 函数库调用是指使用高级语言编写的一组预先编译好的函数,这些函数实现了一些常用的功能,比如:字符串处理、数学计算等。程序员可以在自己的程序中直接调用这些函数,而无需重新实现它们。 |
| 权限 | 执行系统调用时,会从用户态切换到内核态。这是因为系统调用涉及到访问受保护的系统资源,这些操作必须由操作系统控制以确保系统的稳定性和安全性。 | 函数库调用通常在用户态执行,不涉及到用户态与内核态之间的切换。它们直接使用操作系统通过系统调用提供的服务,或者完全在用户空间内完成计算,不需要操作系统介入。 |
| 性能开销 | 由于涉及到用户态与内核态之间的切换,系统调用的执行成本相对较高。因此,频繁的系统调用可能会影响程序的性能。 | 相对于系统调用,函数库调用的性能开销较小。因为它们通常不涉及到模式切换,且执行的操作多在用户空间完成。 |
| 示例 | open()read()write()fork()exec() 等 UNIX/Linux 系统调用。 | C 标准库中的 printf() 等函数;数学库中的 sin()cos() 等函数。 |
> [!NOTE]
>
> - ① **执行层级**:系统调用直接与操作系统内核交互,执行更底层的操作;而函数库调用运行在用户空间,通常使用系统调用来实现其功能。
> - ② **性能开销**:系统调用由于涉及到用户态与内核态的切换,性能开销相对较大;函数库调用则因为主要在用户态执行,性能开销较小。
> - ③ **使用目的**:系统调用提供了访问操作系统资源和服务的能力;函数库调用则提供了方便、高效执行常见任务的手段。
# 第二章:初识计算机语言
## 2.1 计算机语言是什么?
* `人类语言`是人和人之间用于沟通的一种方式,例如:中国人和中国人之间使用普通话沟通,而中国人和美国人交流,则可以使用英语。
* `计算机编程语言`是人和计算机交流的方式。人们可以使用`编程语言`对计算机下达`命令(指令)`,让计算机完成人们需要的功能。
> [!NOTE]
>
> 计算机语言有很多种C、C++、Java、Go、JavaScript、Python、Scala 等。
## 2.2 为什么要学习计算机语言?
* 编程语言到底是什么?编程语言就是由文字和符号组成的,如:
```c
#include <stdio.h> // 这是编译预处理指令
int main() { // 定义主函数
printf("你好,世界!!!"); // 输出所指定的一行信息
return 0; // 函数执行完毕时返回函数值0
}
```
* 编程语言就是用于控制计算机,让其完成我们需要的功能。而我们学习编程语言,其实就是学习这些文字和符号编写的规则。
* 因为 CPU 只能识别二进制的指令,而我们`编写`的程序叫做`源代码`,是人类能看懂;但是,计算机却不能识别。那么,我们就需要让计算机能识别我们编写的源程序,就需要将我们编写的源代码交给编译器程序,其会帮助我们将所编写的源代码转换为计算机能够识别的二进制指令。
> [!NOTE]
>
> 编译器就是运行在操作系统之上的程序,其作用就是用来将程序员编写的源代码转换为计算机能够识别的二进制指令。
* 如果我们用 Java 语言编写了程序(源代码),那么编写的程序也是不能直接运行的,需要通过 Java 语言的编译器将 Java 程序编译为计算机能够识别的二进制指令。
* 如果我们用 Python 语言编写了程序(源代码),那么编写的程序也是不能直接运行的,需要通过 Python 语言的编译器将 Python 程序编译为计算机能够识别的二进制指令。
* ……
* 总而言之,无论我们学习任何一门编程语言,想要将程序运行起来,都必须做如下的两件事情:
* ① 学习该语言的文字和符号编写的规则,即:`语法规则`。
* ② 需要在操作系统上安装对应编程语言的`编译器`程序,将源程序编译为计算机能够识别的二进制指令。
## 2.3 计算机语言简史
### 2.3.1 机器语言(相当于人类的石器时代)
* 1946 年 2 月 14 日,世界上第一台计算机 `ENIAC` 诞生,使用的是最原始的`穿透卡片`。
![](./assets/16.png)
* 这种卡片使用的是用`二进制代码`表示的语言,和人类语言差别极大,这种语言就称为`机器语言`,如:
```txt
0000,0000,000000010000 代表 LOAD A, 16
0000,0001,000000000001 代表 LOAD B, 1
0001,0001,000000010000 代表 STORE B, 16
```
* 这种语言本质上是计算机能识别的`唯一语言`,人类很难理解;换言之,当时的程序员 99.9% 都是异类!!!
> [!IMPORTANT]
>
> 不同类型CPU 架构x86_64、arm 等的处理器有不同的机器语言指令集指令集架构ISA决定了机器语言的具体形式换言之机器语言与特定硬件架构紧密相关机器语言程序几乎没有可移植性。
### 2.3.2 汇编语言(相当于人类的青铜&铁器时代)
* `汇编语言`使用`助记符`MOV、ADD、SUB代替二进制操作码使程序更易于人类编写和理解因此`汇编语言`也被称为`符号语言`。
![](./assets/17.png)
* 汇编语言的`优点`是能编写`高效率`的程序;但是,`缺点`和机器语言没什么不同,汇编语言同样`依赖于具体的计算机架构(面向机器)`,程序不具备跨平台的可移植性。
> [!NOTE]
>
> 汇编语言,目前仍然应用于工业电子编程领域、软件的加密解密、计算机病毒分析等。
### 2.3.3 高级语言(相当于人类的信息时代)
* `高级语言`是一种`接近于人们使用习惯`的程序设计语言。`它允许程序员使用接近日常英语的指令来编写程序`,程序中的符号和算式也和`日常使用的数学公式`差不多,接近于自然语言和数学语言,容易被人们掌握。
![](./assets/18.png)
* 高级语言`独立于计算机硬件`,有一定的通用性;计算机不能直接识别和执行用高级语言编写的程序,需要使用`编译器`或`解释器`转换为机器语言,才能被计算机识别和执行。
![](./assets/19.png)
> [!NOTE]
>
> 普遍使用的高级编程语言C、C++、Java、Python、C#、JavaScript、Go、SQL 等。
### 2.3.4 总结
* 编写语言的对比,如下所示:
| 类别 | 特征 | 优点 | 缺点 | 示例 |
| :----------- | :--------------------------------- | :----------------------------------------------- | :----------------------------------------------------------- | :------------------ |
| **机器语言** | 直接由计算机执行的二进制代码 | 执行速度快 | 编写困难,可读性差,与具体硬件强绑定 | 二进制代码 |
| **汇编语言** | 用助记符代替二进制代码的低级语言 | 相对机器语言更易编写和理解,允许直接控制硬件资源 | 依然需要了解硬件,不够抽象,与具体硬件或平台相关 | MOVADD 等助记符 |
| **高级语言** | 接近人类语言,提供了更高层次的抽象 | 易于编写和维护,可移植性好,支持多种编程范式 | 需要通过编译器或解释器转换为机器语言,可能存在一定的性能损失 | CJava Python 等 |
> [!NOTE]
>
> - ① 这三种编程语言类型从低级到高级提供了不同层次的抽象,以满足不同的编程需求和场景。
> - ② 随着计算机科学的发展,高级语言因其强大的表达能力、良好的可移植性和易用性,成为了日常软件开发的主流选择。
# 第三章:初识 C 语言
## 3.1 C 语言的由来
* 1969 年,美国贝尔实验室的`肯·汤姆森`Ken Thompson和`丹尼斯·里奇`Dennis Ritchie一起开发了 Unix 操作系统。Unix 最初是使用`汇编语言`编写的,依赖于计算机硬件。为了程序的`可读性`和`可移植性`,它们决定使用高级语言重写。但是。当时的高级语言无法满足他们的要求,`肯·汤姆森`就在 BCPL 语言的基础上发明了 `B` 语言。
* 1972 年,`丹尼斯·里奇`Dennis Ritchie`B` 语言的基础上重新设计了一种新的语言,这种新语言取代了 `B` 语言,即 `C` 语言。
![](./assets/20.png)
* 1973 年,`整个 Unix 系统都使用 C 语言重写`。
> [!NOTE]
>
> C 语言最初是作为 Unix 系统的开发工具而发明的。
* 此后这种语言快速流传广泛用于各种操作系统和系统软件的开发Unix、MS-DOS、Microsoft Windows 以及 Linux 等。
![](./assets/21.png)
* 1988 年美国国家标准协会ANSI正式将 `C 语言标准化`,标志着 C 语言开始稳定和规范化。
## 3.2 为什么要学习 C 语言?
* ① `C 语言具有可移植好、跨平台的特点`:用 C 语言编写的代码可以在不同的操作系统和硬件平台上编译和运行。
> [!NOTE]
>
> C 语言的最原始的设计目的,就是为了将 Unix 操作系统移植到其他的计算机架构上,这使得它从一开始就非常注重可移植性。
* ② `C 语言在许多领域应用广泛`
* `操作系统`C 广泛用于开发操作系统Unix、Linux 和 Windows。
* `嵌入式系统`C 是一种用于开发嵌入式系统(如:微控制器、微处理器和其它电子设备)的流程语言。
* `系统软件`C 用于开发设备驱动程序、编译器和汇编器等系统软件。
* `网络`C 语言广泛用于开发网络应用程序例如Web 服务器、网络协议和网络驱动程序。
* `数据库系统`C 用于开发数据库系统例如Oracle、MySQL 和 PostgreSQL 。
* `游戏`:由于 C 能够处理低级硬件交互,因此经常用于开发计算机游戏。
* `人工智能`C 用于开发人工智能和机器学习的应用程序,例如:神经网络和深度学习算法。
* `科学应用`C 用于开发科学应用程序,例如:仿真软件和数值分析工具。
* `金融应用`C 用于开发股票市场分析和交易系统等金融应用。
* ③ C 语言能够直接对硬件进行操作、管理内存以及和操作系统对话,这使得它是一种非常接近底层的语言,非常适合`写需要和硬件交互、有极高性能要求`的程序。
* ④ `学习 C 语言有助于快速上手其他编程语言`C++(原先是 C 语言的一个扩展,在 C 语言的基础上嫁接了面向对象编程思想、C#、Java 等,这些语言都继承或深受 C 语言的影响和启发。
* ⑤ C 语言长盛不衰。`C 语言至今,依然是最广泛使用、最流行的编程语言之一`,包括很多大学将 C 语言作为计算机教学的入门语言,拥有庞大而活跃的用户社区,这意味着有许多资源和库可供开发人员使用。
## 3.3 计算机语言排行榜
* [TIOBE](https://www.tiobe.com/tiobe-index/) 是一个流行编程语言排行每月更新。排名权重基于世界范围内工程师数量Google、Bing、Yahoo! 、Wikipedia、Amazon、Youtube 和百度这些主流的搜索引擎,也将作为排名权重的参考指标。
![](./assets/22.png)
* 计算机语言走势图:
![](./assets/23.png)
## 3.4 C 语言的版本选择
* 随着微型计算机的日益普及,出现了许多 C 语言版本(标准)。
* 版本 1KR CK&R C 指的是 C 语言的原始版本。1978年C 语言的发明者布莱恩·柯林Brian `K`ernighan和丹尼斯·里奇Dennis `R`itchie合写了一本著名的教材《C 编程语言》The C programming language
>[!NOTE]
>
>由于 C 语言还没有成文的语法标准,这本书就成了公认标准,以两位作者的姓氏首字母作为版本简称 “K&R C”。
* 版本 2ANSI C又称 C89 或 C90C 语言的原始版本非常简单,对很多情况的描述非常模糊,加上 C 语法依然在快速发展,要求将 C 语言标准化的呼声越来越高。1989 年美国国家标准协会ANSI制定了一套 C 语言标准并于次年被国际标准化组织ISO通过。它被称为 “ANSI C”也可以按照发布年份称为 “C89 或 C90”。
* 版本 3C99C 语言标准的第一次`大型修订`,发生在 1999 年,增加了许多语言特性,比如:双斜杠( // )的注释语法,可变长度数组、灵活的数组成员、复数、内联函数和指定的初始值设定项,这个版本称为 C99`是目前最流行的 C 版本`。
* 版本 4C112011 年,标准化组织再一次对 C 语言进行修订增加了_Generic、static_assert 和原子类型限定符。这个版本称为 C11。
> [!NOTE]
>
> 需要强调的是,修订标准的原因并不是因为原标准不能用,而是需要跟进新的技术。
* 版本 5C17C11 标准在 2017 年进行了修补,但发布是在 2018 年。新版本只是解决了 C11 的一些缺陷,没有引入任何新功能。这个版本称为 C17。
* 版本 6C232023 年发布,计划进一步增强安全性,消除实现定义的行为,引入模块化语言概念等新特性,使 C 语言在安全和可靠性方面有重大提高。
* ……
* 需要注意的是C 语言的标准并没有强制性的约束,只是个说明文档而已。不同的编译器产商,对 C 语言的标准有不同的实现,甚至会出现某些 C 语言的标准在这个编译器下实现了;但是,在另外的编辑器下却没有实现,导致编译程序错误的现象。常见的 C/C++ 编译器如下:
* Borland C++ 宝蓝公司。
* Intel C++ 英特尔编译器。
* MSVC 微软公司。
* g++ 编译器GCC编译套件, Linux 操作系统。
> [!IMPORTANT]
>
> GCC 编译套件对标准的支持是最好的;所以,在实际项目开发中,我们首先会选用 GCC 编译套件来进行开发。
## 3.5 C 语言的优缺点
* C 语言的优点:
* ① 高效C 语言生成的代码非常高效,执行速度快,这使得其非常适合用于操作系统、嵌入式系统等需要高性能的场景。
* ② 灵活性和低级控制C 语言允许直接操作内存和硬件,可以进行位操作、指针运算等底层编程,非常适合开发需要直接硬件控制的应用。
* ③ 广泛的硬件和平台支持C 语言几乎可以在所有的计算机平台上运行,从微处理器到超级计算机,几乎所有的硬件平台都支持 C 语言。
* ④ 标准库丰富C 语言有一个标准库C Standard Library提供了大量常用的函数涵盖了文件操作、字符串处理、内存管理等多种功能。
* ⑤ 语言简洁:语法规则相对简单,没有过多的复杂特性,使得语言本身比较容易学习和掌握。
* C 语言的缺点:
* ① 缺乏高级特性和现代编程语言相对C 语言缺乏一些高级特性,如:面向对象编程、垃圾回收机制等,这使得某些类型的应用程序开发可能会更加复杂。
* ② 安全性问题C 语言允许直接操作内存,可能会导致缓冲区溢出、空指针引用等安全漏洞。如果不小心处理,容易产生难以调试的错误和安全隐患。
* ③ 手动管理内存C 语言需要程序员手动管理内存,即:分配内存和释放内存,这增加了内存泄露和悬空指针等问题的风险。
* ④ 错误调试困难:由于 C 语言的底层操作特点,调试和排查错误可能比较困难,尤其是在处理复杂指针和内存操作的时候。
* ⑤ 标准库有限:虽然 C 语言的标准库涵盖了很多基本功能,但相比现代编程语言的标准库,功能相对有限,尤其是在网络编程、多线程编程等方面。
* 总而言之C 语言的高效性和灵活性使其在系统级编程和嵌入式系统中占据重要地位但其缺乏高级特性和内存管理上的挑战也使得开发过程可能更加复杂和容易出错。对于需要高性能和底层控制的应用C 语言依然是不可替代的选择。
# 第四章C 语言入门Hello World
## 4.1 环境的安装和配置
### 4.1.1 概述
* 要开发 C/C++ 程序,需要安装 C/C++ 编译器,目前有两种主流实现,即:
* GCCGNU Compiler Collection全平台实现即支持 Windows、MacOS、Linux 等。
* MSVCMicrosoft Visual C++):只支持 Windows 系统。
* GCC 在 Windows 上的版本有很多,如:[MinGW-w64](https://www.mingw-w64.org/)、[Gygwin](https://cygwin.com/)、[MSYS2](https://www.msys2.org/)。它们之间的区别,如下所示:
| 特性 | MinGW-w64 | Cygwin | MSYS2 |
| ------------ | ----------------------------- | ------------------------------------- | ----------------------------------------------------- |
| **简介** | Minimalist GNU for Windows | POSIX 兼容环境和工具集 | 结合了 MinGW 和 Cygwin 的工具集 |
| **编译器** | 提供 GCC 编译器 | 提供 POSIX 兼容环境,包含大量工具 | 提供 MinGW-w64 工具链和 Cygwin 环境 |
| **生成文件** | Windows 原生可执行文件 | POSIX 兼容的可执行文件 | 可以生成 Windows 原生可执行文件或 POSIX 文件 |
| **依赖** | 无需额外依赖 | 依赖 Cygwin DLL | 根据使用工具链决定MinGW-w64 无依赖Cygwin 有依赖) |
| **工具和库** | 基本的编译工具 | 丰富的 Unix 工具和库 | 丰富的工具和库,强大的包管理系统 |
| **性能** | 性能较好 | 可能较低,因为通过兼容层调用系统 | 取决于使用的工具链MinGW-w64 性能较好) |
| **复杂度** | 简单易用 | 设置和使用相对复杂 | 较为灵活,复杂度介于 MinGW-w64 和 Cygwin 之间 |
| **适用场景** | 开发 Windows 原生应用 | 运行和开发 Unix 程序 | 混合使用 Unix 工具和开发 Windows 原生应用 |
| **优点** | 轻量级,直接生成 Windows 应用 | 完整的 POSIX 兼容环境,丰富的工具 | 灵活的环境,强大的包管理系统 |
| **缺点** | 工具和库较少 | 生成文件依赖 Cygwin DLL性能可能较低 | 环境较大,占用更多空间,复杂性比 MinGW-w64 高 |
> [!NOTE]
>
> * ① MinGW-w64 、Cygwin 以及 MSYS2 任选其一安装即可。
> * ② 目前的 Win10 和 Win11 版本支持 WSL2 Windows Sub Linux 2 ,即 Windows 的子系统 Linux可以实现在 Windows 系统上安装一个 Linux ,然后再运行 Linux 中的 GCC 工具链。
### 4.1.2 MinGW-w64 的安装和配置
#### 4.1.2.1 安装
* 下载到本地:略。
> [!NOTE]
>
> 下载地址在[这里](https://github.com/niXman/mingw-builds-binaries/releases/download/13.2.0-rt_v11-rev1/x86_64-13.2.0-release-posix-seh-ucrt-rt_v11-rev1.7z)。
![](./assets/24.png)
* 解压到指定的目录,即:
![](./assets/25.png)
> [!NOTE]
>
> 本人的解压目录是:`D:\develop\mingw64` 。
#### 4.1.2.2 配置 path 环境变量
* 配置环境变量,以便任意目录都可以执行 gcc 命令,即:
![](./assets/26.png)
![](./assets/27.png)
![](./assets/28.png)
![](./assets/29.png)
![](./assets/30.png)
> [!NOTE]
>
> 因为,本人安装 MinGW-w64 的目录是 `D:\develop\mingw64`,所以配置 path 环境变量就需要 `D:\develop\mingw64\bin`
![](./assets/31.png)
* 测试是否安装成功:
```shell
gcc --version
```
![](./assets/32.gif)
### 4.1.3 Cygwin 的安装和配置
#### 4.1.3.1 安装
* 下载到本地:略。
> [!NOTE]
>
> 下载地址在[这里](https://www.cygwin.com/install.html)。
![](./assets/33.png)
* 点击安装:
![](./assets/34.png)
![](./assets/35.png)
![](./assets/36.png)
![](./assets/37.png)
![](./assets/38.png)
![](./assets/39.png)
![](./assets/40.png)
![](./assets/41.png)
> [!NOTE]
>
> 默认是最小化安装,没有 GCC需要选择 gcc-core、gcc-g++、make、gdb、binutils 。
![](./assets/42.png)
![](./assets/43.png)
![](./assets/44.png)
![](./assets/45.png)
![](./assets/46.png)
![](./assets/47.png)
![](./assets/48.png)
![](./assets/49.png)
![](./assets/50.png)
#### 4.1.3.2 配置 path 环境变量
* 和 `3.1.2.2 配置 path 环境变量` 步骤相同:略。
### 4.1.4 MSYS2推荐
#### 4.1.4.1 安装
* 下载到本地:略。
> [!NOTE]
>
> 下载地址在[这里](https://www.msys2.org/)。
![](./assets/51.png)
* 点击安装:
![](./assets/52.png)
![](./assets/53.png)
![](./assets/54.png)
![](./assets/55.png)
![](./assets/56.png)
* 出现命令终端:
![](./assets/57.png)
* 替换清华镜像源(可选):
```shell
sed -i "s#https\?://mirror.msys2.org/#https://mirrors.tuna.tsinghua.edu.cn/msys2/#g" /etc/pacman.d/mirrorlist*
```
![](./assets/58.gif)
* 安装 gcc 等相关开发包:
```shell
pacman -Syu --noconfirm # 更新包管理器
```
```shell
pacman -Sy base-devel --noconfirm # 安装开发工具包
```
```shell
pacman -Sy mingw-w64-x86_64-toolchain --noconfirm # 安装开发 gcc 相关工具链
```
![](./assets/59.gif)
#### 4.1.4.2 配置 path 环境变量
* 和 `3.1.2.2 配置 path 环境变量` 步骤相同:略。
## 4.2 IDE 的安装和配置
### 4.2.1 CLion
#### 4.2.1.1 概述
* [CLion](https://www.jetbrains.com/clion/) 是一款由 JetBrains 推出的跨平台 C/C++ 集成开发环境IDE它具有智能编辑器、CMake 构建支持、调试器、单元测试、代码分析等功能,可以极大提高 C/C++ 开发效率。
#### 4.2.1.2 安装
* 鼠标双击,进入安装:
![](./assets/60.png)
* 下一步:
![](./assets/61.png)
* 下一步:
![](./assets/62.png)
* 下一步:
![](./assets/63.png)
* 安装:
![](./assets/64.png)
* 安装完成:
![](./assets/65.png)
#### 4.2.1.3 配置
* 打开 CLion
![](./assets/66.png)
* 安装中文插件(可选):
![](./assets/67.png)
![](./assets/68.png)
* 配置新 UI
![](./assets/69.png)
![](./assets/70.png)
* 新 UI 配置自定义字体(可选):
![](./assets/71.png)
* 配置`自动保存`功能:
![](./assets/72.png)
* 配置`文件编码` 为 UTF-8
![](./assets/73.png)
* 配置`控制台编码`为 UTF-8
![](./assets/74.png)
* 配置`显示方法分隔符`功能:
![](./assets/75.png)
* 配置`编辑器`的字体(可选):
![](./assets/76.png)
* 检测 GCC 工具链是否安装成功:
![](./assets/77.png)
### 4.2.2 VS Code
#### 4.2.2.1 概述
* [Visual Studio Code (VS Code)](https://code.visualstudio.com/) 是一个免费的开源代码编辑器,适用于 Windows、MacOS 和 Linux 平台。它支持语法高亮、智能代码补全IntelliSense、内置调试工具和Git集成。用户可以通过扩展来添加更多功能支持新的编程语言、主题和调试工具。VS Code 还支持在微软 Azure 上进行部署和托管,适用于各种编程语言和框架。
> [!NOTE]
>
> Visual Studio Code 需要安装对应的插件,才能运行 C/C++ 代码。
#### 4.2.2.2 安装
* 鼠标双击,进入安装:
![](./assets/78.png)
* 同意协议:
![](./assets/79.png)
* 下一步:
![](./assets/80.png)
* 下一步:
![](./assets/81.png)
* 下一步:
![](./assets/82.png)
* 安装:
![](./assets/83.png)
* 安装过程:
![](./assets/84.png)
* 安装完成:
![](./assets/85.png)
#### 4.2.2.3 配置
* 安装`中文`插件:
![](./assets/86.png)
![](./assets/87.png)
* 安装 `C/C++` 插件:
![](./assets/88.png)
![](./assets/89.png)
### 4.2.3 Microsoft Visual Studio
#### 4.2.3.1 概述
* [Visual Studio](https://visualstudio.microsoft.com/)(简称 VS是由微软公司发布的集成开发环境。它包括了整个软件生命周期中所需要的大部分工具UML工具、代码管控工具、集成开发环境IDE等。
* Visual Studio 支持 C/C++、C#、F#、VB 等多种程序语言的开发和测试可以用于生成Web应用程序也可以生成桌面应用程序功能十分强大但下载和安装很可能耗时数小时还可能会塞满磁盘。
* Visual Studio 2022 有三种版本:社区版(免费,不支持企业使用),专业版(第一年 1199 美元/ 799 美元续订)和企业版(第一年 5999 美元/ 2569 美元续订)。企业版拥有面向架构师的功能、高级调试和测试,这些功能是另两种 SKU 所没有的。
* Visual Studio 旨在成为世界上最好的 IDE集成开发环境目前最新版本为 Visual Studio 2022。
#### 4.2.3.2 安装
* 鼠标双击,进入安装:
![](./assets/90.png)
* 继续:
![](./assets/91.png)
* 等待:
![](./assets/92.png)
* 工作负荷(使用 C++ 的桌面开发):
![](./assets/93.png)
* 单个组件:
![](./assets/94.png)
* 语言包:
![](./assets/95.png)
* 安装位置(修改默认的安装位置):
![](./assets/96.png)
* 如果不是第一次安装,可能会出现`共享组件、工具和 SDK`不可以修改,即:
![](./assets/97.png)
* 此时,就需要打开`注册表编辑器`,将如下图中的除了第一个选项,全部删除,然后关闭再重新安装,即:
![](./assets/98.png)
* 开始安装:
![](./assets/99.png)
* 安装中:
![](./assets/100.png)
* 安装完成,然后关闭:
![](./assets/101.png)
#### 4.2.3.3 配置
* 在开始菜单处,启动 VS
![](./assets/102.png)
* 登录或跳过该选项(有微软账号就注册,没有就暂时跳过):
![](./assets/103.png)
* 继续:
![](./assets/104.png)
* 注册 VS
![](./assets/105.png)
* 填写注册码:
> [!NOTE]
>
> * ① Pro 版本:`TD244-P4NB7-YQ6XK-Y8MMM-YWV2J`
> * ② Enterprise 版本:`VHF9H-NXBBB-638P6-6JHCY-88JWH`
![](./assets/106.png)
![](./assets/107.png)
## 4.3 HelloWorld
### 4.3.1 手动版
* ① 新建一个 `HelloWorld.c` 的文件:
![](./assets/108.png)
* ② 通过`记事本`等软件打开该文件,输入如下的代码,并保存:
```c
#include <stdio.h>
int main(){
printf("Hello World");
return 0;
}
```
![](./assets/109.gif)
* ③ 通过 `gcc` 命令编译该文件:
```shell
gcc HelloWorld.c -o HelloWorld.exe
```
![](./assets/110.gif)
* ④ 执行:
```shell
./HelloWorld.exe
```
![](./assets/111.gif)
### 4.3.2 VS Code 版
* ① 新建一个`空`文件夹(目录),用于存放代码:
![](./assets/112.png)
* ② 通过 `vscode` 打开该目录:
![](./assets/113.gif)
* ③ 在 `vscode` 中新建 `HelloWorld.c` 文件:
![](./assets/114.gif)
* ④ 设置 VSCode 中 C/C++ 的代码格式为行尾风格(可选):
![](./assets/115.png)
![](./assets/116.png)
* ⑤ 编写如下的代码,并保存:
```c
#include <stdio.h>
int main(){
printf("Hello World");
return 0;
}
```
![](./assets/117.gif)
* ⑥ 通过 `gcc` 命令编译该文件:
```shell
gcc HelloWorld.c -o HelloWorld.exe
```
![](./assets/118.gif)
* ⑦ 执行:
```shell
./HelloWorld.exe
```
![](./assets/119.gif)
* ⑧ 安装 Code Runner 插件(步骤略),实现右键直接编译执行(可选):
![](./assets/120.gif)
### 4.3.3 VS 版
* ① 新建空项目:
![](./assets/121.png)
![](./assets/122.png)
![](./assets/123.png)
![](./assets/124.png)
* ② 打开`解决方案资源管理器`
![](./assets/125.png)
![](./assets/126.png)
* ③ 新建 `HelloWorld.c` 文件:
![](./assets/127.gif)
* ④ 编写如下代码,并保存:
```c
#include <stdio.h>
int main(){
printf("Hello World");
return 0;
}
```
![](./assets/128.gif)
* ⑤ 编译和执行:
![](./assets/129.gif)
### 4.3.4 CLion
* ① 新建空项目:
![](./assets/130.png)
![](./assets/131.png)
![](./assets/132.png)
* ② 编写如下代码,并保存:
```c
#include <stdio.h>
int main(){
printf("Hello World");
return 0;
}
```
![](./assets/133.gif)
* ③ 编译和运行:
![](./assets/134.gif)
* ④ 默认情况下,一个项目只能有一个 c 源文件包含 main 函数,但是 CLion 可以有多个,如下:
![](./assets/135.gif)
* ⑤ 如果之后,有中文乱码问题,那么请做如下步骤:
![](./assets/136.png)
![](./assets/137.gif)
> [!NOTE]
>
> 内容如下所示:
>
> ```txt
> -Dfile.encoding=UTF-8
> -Dconsole.encoding=UTF-8
> ```
# 第五章:注释
## 5.1 概述
* 编程语言中,`注释`是一种`特殊`的文本,它不会被编译器执行,而仅用于代码的解释和文档说明。
>[!NOTE]
>
>* ① 注释是一个程序员必须有具有的良好编程习惯。
>* ② 在实际开发中,程序员可以将自己的思路通过`注释`整理出来,然后再用`代码`去实现。
## 5.2 单行注释
* C 语言中的单行注释的格式,如下所示:
```c
// 单行注释
```
> [!NOTE]
>
> 在 CLion 中的快捷键是 `Ctrl + /`
* 示例:
```c
#include <stdio.h> // 这是编译预处理指令
int main() { // 定义主函数
printf("你好,世界!!!"); // 输出所指定的一行信息
return 0; // 函数执行完毕时返回函数值0
}
```
## 5.3 多行注释
* C 语言中的多行注释的格式,如下所示:
```c
/*
 这是第一行注释
 这是第二行注释
 这是第三行注释
*/
```
>[!NOTE]
>
>* ① 多行注释不能嵌套使用!!!
>* ② 在 CLion 中的快捷键是 `Ctrl + Alt + /`
* 示例:
```c
#include <stdio.h>
int main() {
/*
printf(1);
printf(2);
*/
printf("你好,世界!!!");
return 0;
}
```
# 第六章HelloWorld 的规范(⭐)
## 6.1 规范的代码风格
### 6.1.1 正确的缩进和空白
* ① 使用一次 `tab` 操作,实现缩进,默认整体向右边移动;如果使用 `shift + tab` 则整体向左移动。
* ② 运算符两边习惯各加一个空格,如:`2 + 4 = 6`。
> [!NOTE]
>
> 各种 IDE 都有格式化的快捷键CLion 的格式化快捷键是 `Ctrl + Alt + L`
* 示例:
```c
#include <stdio.h>
int main() {
int a = 1;
int b = 2;
int c = a + b;
printf("c = %d", c);
return 0;
}
```
### 6.1.2 代码风格
* 在 C 语言中,有两种代码风格:`行尾风格`和`次行风格`。
>[!NOTE]
>
>看个人爱好,任选一种即可,本人喜欢`行尾分格`
* 示例:行尾风格
```c
int main(){
if(a > b) {
return a;
} else {
return b;
}
  return 0;
}
```
* 示例:次行风格
```c
int main()
{
if(a > b)
{
return a;
}
else
{
return b;
}
  return 0;
}
```
## 6.2 代码细节剖析
### 6.2.1 main() 函数
* 在 C 语言中,一个程序或工程可以定义很多函数,但是有且只有一个 main() 函数,作为程序执行的入口,并且在 main() 函数结尾结束整个程序的运行,即:
```c
int main(){
return 0;
}
```
* 如果 main() 函数是空括号,即表示 main() 函数不接收任何参数。
* 在 main() 函数之前的 `int` 称为关键字,代表数据类型是`整型`,它是 main() 函数的返回值的类型,即在执行 main() 函数之后一定会得到一个整数类型的值,即函数值。
> [!NOTE]
>
> * ① 在 C 语言中,人们约定,如果 `return 0`,就表示 main() 函数终止运行,且运行成功;如果返回其它非零整数,则表示运行失败。
> * ② 默认情况下,如果 main() 函数中省略 `return 0` ,则编译器会自动加上;但是,为了保持统一的代码风格,不建议省略。
### 6.2.2 函数体
* ① 一对花括号 `{}` 定义了函数的主体,所有函数都必须以大括号开头和结尾,成对出现。
* ② C 程序中的函数体指的是作为该函数一部分的语句。它可以是任何操作,比如:搜索、排序、打印等。
* ③ 每一个执行语句后面都会有一个英文分号`;`作为语句结束的标志。
* ④ 一行内可写几条语句,一条语句也可写在几行上。
### 6.2.3 printf() 函数
* printf() 函数的格式,如下所示:
```c
printf (const char *__format, ...)
```
* printf() 函数是产生格式化输出的函数作用是将参数文本输出到屏幕f 表示 format格式化表示可以指定输出文本的格式
```c
printf ("Hello World"); // 将字符串输出到控制台,行尾不换行
```
* 如果想让光标移动到下一行的开头,可以在输出文本的结尾,可以添加一个换行符 `\n`,即:
```c
printf("Hello World\n");
```
### 6.2.4 标准库和头文件
#### 6.2.4.1 概述
* printf() 函数是在标准库的头文件 `stdio.h` 中定义的,要想在程序中使用这个函数,必须在源文件的头部引入该头文件,即:
```c
#include <stdio.h>
```
#### 6.2.4.2 标准库Standard Library
* C 语言的`标准库`是由一组函数组成,这些函数提供了许多常用的操作和功能,如:输入输出、字符串处理、内存管理、数学计算等。标准库中的函数由编译器提供,遵循 ANSI C 标准C89/C90、C99、C11等
* 换言之C 语言的`标准库`就是包含函数的实际代码这些代码在编译的时候被链接到我们的程序中无需手动包含。C 语言的`标准库`提供了可重用的函数实现,使得程序员不必编写常用的功能。
> [!NOTE]
>
> 实际的 printf() 函数的实现代码通常位于标准库的实现文件中,如:在 Linux 中的标准库`libc.so.6` 就包含了 printf() 函数的实现。
#### 6.2.4.3 头文件Header Files
* `头文件`是包含函数声明、宏定义、数据类型定义等内容的文件。头文件的作用是为源代码提供必要的声明和定义,以便编译器能够正确解析和链接函数调用。头文件通常以`.h`作为文件扩展名。
* 换言之,头文件包含函数声明、宏定义和数据类型定义,但不包含函数的实现。头文件告知编译器如何使用标准库中的函数和定义,确保编译时的正确性。头文件需要在源代码文件中使用`#include`指令显式包含,如:`#include <stdio.h>`。
* 常见的 C 语言头文件及其功能和常用函数、宏等,如下所示:
| 头文件 | 功能说明 | 常用函数和宏 |
| ------------- | ---------------------------------------------------------- | ------------------------------------------------------------ |
| **stdio.h** | 标准输入输出库 | `printf` `scanf` `fprintf``fscanf``fopen` `fclose``fgets` `fputs` |
| **stdlib.h** | 标准库,提供内存分配、程序控制、类型转换、随机数生成等功能 | `malloc` `free` `exit` `atoi` `atof``rand``srand` |
| **string.h** | 字符串处理库 | `strlen` `strcpy` `strncpy` `strcat` `strcmp``strstr` `memset` `memcpy` |
| **math.h** | 数学库 | `sin` `cos` `tan` `exp` `log` `sqrt` `pow` |
| **time.h** | 时间和日期库 | `time` `clock` `difftime` `mktime` `strftime` `localtime``gmtime` |
| **ctype.h** | 字符处理库 | `isalnum` `isalpha` `isdigit` `islower` `isupper` `tolower` `toupper` |
| **stdbool.h** | 布尔类型库 | `bool` `true` `false` |
| **assert.h** | 断言库 | `assert` |
#### 6.2.4.4 预处理命令
* `#include` 命令的作用是将指定文件的内容插入到包含该命令的源文件中。这通常用于包含头文件,以便使用头文件中声明的函数、宏和数据类型。
* 语法:
```c
// 用于包含标准库头文件或系统头文件。
// 编译器将在系统的标准头文件目录中查找文件。
#include <filename>
```
```c
// 用于包含用户自定义的头文件。
// 编译器首先在当前目录中查找文件,如果未找到,再在标准头文件目录中查找。
#include "filename"
```
# 第七章CLion 高级配置(⭐)
## 7.1 安装和配置 WSL2
### 7.1.1 概述
* WSL 2全称为 Windows Subsystem for Linux 2是微软提供的一种技术允许用户在 Windows 操作系统上运行 Linux 内核。WSL 2 是 WSL 的升级版,它引入了一个真正的 Linux 内核来代替 WSL 1 中使用的兼容层,从而提供更高的性能和更广泛的系统调用支持。
* 其架构图,如下所示:
![](./assets/138.png)
* WSL2 的功能,如下所示:
* ① **真实的Linux内核**WSL 2 使用了微软开发的轻量级虚拟机,它包含了一个完整的 Linux 内核。这意味着 WSL 2 能够运行更多的 Linux 应用程序,并且支持更多的系统调用。
* ② **文件系统性能提升**WSL 2 的文件系统性能比 WSL 1 有显著提升。对于 I/O 密集型的操作编译代码或数据库操作WSL 2 能够提供更快的速度。
* ③ **兼容性增强**:由于使用了真实的 Linux 内核WSL 2 对 Linux 应用程序的兼容性大幅提高。许多在 WSL 1上不能运行或需要调整的应用程序可以在 WSL 2上直接运行。
* ④ **网络功能改进**WSL 2 提供了更好的网络集成,能够更容易地与 Windows 上的其他网络资源进行交互。
* ⑤ **资源使用优化**WSL 2 使用轻量级虚拟机,比传统的虚拟机占用更少的资源,同时提供了类似的隔离和安全性。
* WSL 的用途,如下所示:
* ① **开发环境**WSL 2 为开发者提供了一个原生的Linux开发环境而无需离开 Windows 。这对于需要在 Linux 上开发、测试或运行应用程序的开发者非常有帮助。
* ② **学习和实验**:用户可以使用 WSL 2 在Windows上学习和实验 Linux 命令行工具和应用程序,而无需设置双重引导系统或安装虚拟机。
* ③ **多平台开发**对于跨平台开发者来说WSL 2 允许他们在一个操作系统上同时进行 Windows 和 Linux 平台的开发和测试,提高工作效率。
* ④ **运行 Linux 工具和应用程序**WSL 2 支持在 Windows 上直接运行各种 Linux 工具和应用程序Docker、数据库、编程语言环境等。
### 7.1.2 WSL2 的安装
* ① BIOS 或 UEFI 中,开启虚拟化:步骤略。
![](./assets/139.png)
* ② 查看是否开启了虚拟化:
![](./assets/140.png)
* ③ 启用适用于 Linux 的 Windows 子系统:
```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
```
> [!IMPORTANT]
>
> 以管理员身份打开 PowerShell 并运行,执行完上述命令之后,如果提示需要重启计算机,那就重启计算机。
![](./assets/141.gif)
* ④ 启用虚拟机功能:
```powershell
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```
> [!IMPORTANT]
>
> 以管理员身份打开 PowerShell 并运行,执行完上述命令之后,如果提示需要重启计算机,那就重启计算机。
![](./assets/142.gif)
* ⑤ 更新 Linux 内核包:
```powershell
wsl --update
```
> [!NOTE]
>
> wsl2 的最新 Linux 内核包托管在 GitHub 上,某些国家可能会污染 Github 相关的域名,那么就需要手动下载,然后安装即可,下载地址在[这里](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi)。
![](./assets/143.gif)
* ⑥ 将 wsl2 设置为默认版本:
```powershell
wsl --set-default-version 2
```
![](./assets/144.gif)
* ⑦ 查看官方在线支持的 Linux 版本:
```powershell
wsl --list --online
```
![](./assets/145.gif)
* ⑧ 安装指定版本的 Linux
```powershell
wsl --install Ubuntu-24.04
```
> [!NOTE]
>
> 官方支持的 Linux 版本,托管在 Github 上,某些国家可能会污染 Github 的域名;此时,要么走科学上网,要么在 `Microsoft Store` 中搜索并安装。
![](./assets/146.gif)
* ⑨ 在 Microsoft Store 中搜索并安装(可选):
![](./assets/147.png)
* ⑩ 查询本地安装的 Linux 版本:
```powershell
wsl --list
```
![](./assets/148.gif)
### 7.1.3 配置 WSL2
* 本人的安装的是 AlmaLinux9 ,所以需要执行如下命令,以便安装 cmake 相关工具链:
```shell
sudo dnf update -y # 更新包管理器
sudo dnf groupinstall "Development Tools" -y # 安装开发工具包
sudo dnf install gcc gcc-c++ -y # 安装GCC相关工具链
sudo dnf install cmake -y # 安装 cmake
sudo dnf install make -y # 安装 make
sudo dnf install gdb -y # 安装 gdb
```
![](./assets/149.gif)
* 可以通过 CLion 测试是否安装成功:
![](./assets/150.gif)
### 7.1.4 配置 WSL2
* 本人的安装的是 Ubuntu 24.04,所以需要执行如下命令,以便安装 cmake 相关工具链:
```shell
sudo apt update && sudo apt upgrade -y # 更新包管理器
sudo apt install build-essential -y # 安装开发工具包
sudo apt install gcc g++ -y # 安装 GCC 相关工具链
sudo apt install cmake -y # 安装 cmake
sudo apt install gdb -y # 安装 gdb
```
![](./assets/151.gif)
* 可以通过 CLion 测试是否安装成功:
> [!NOTE]
>
> 默认仓库中的 GDB 的版本会很高CLion 会不支持,那么就需要手动下载源码,自行编译,本次不再演示!!!
![](./assets/152.gif)
## 7.2 切换 CLion 中的 cmake 的工具链
* 可以在 CLoin 中切换 cmake 的工具链,以便支持不同平台的 cmake ,即:
![](./assets/153.gif)
## 7.3 修改 CMakeLists.txt 文件
* 前文也提到了,在一个 C 语言项目中,只能有一个 main() 函数;但是,我们可以修改 `CMakeLists.txt` 文件的内容,以便其支持在一个 C 语言项目中,可以有多个包含 main() 函数的文件,如下所示:
![](./assets/154.png)
* `CMakeLists.txt` 的内容,如下所示:
```txt
cmake_minimum_required(VERSION 3.10)
# 项目名称和版本号
project(c-study VERSION 1.0 LANGUAGES C)
# 设置 C 标准
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED True)
# 辅助函数,用于递归查找所有源文件
function(collect_sources result dir)
file(GLOB_RECURSE new_sources "${dir}/*.c")
set(${result} ${${result}} ${new_sources} PARENT_SCOPE)
endfunction()
# 查找顶层 include 目录(如果存在)
if (EXISTS "${CMAKE_SOURCE_DIR}/include")
include_directories(${CMAKE_SOURCE_DIR}/include)
endif ()
# 查找所有源文件
set(SOURCES)
collect_sources(SOURCES ${CMAKE_SOURCE_DIR})
# 用于存储已经处理过的可执行文件名,防止重复
set(EXECUTABLE_NAMES)
# 创建可执行文件
foreach (SOURCE ${SOURCES})
# 获取文件的相对路径
file(RELATIVE_PATH REL_PATH ${CMAKE_SOURCE_DIR} ${SOURCE})
# 将路径中的斜杠替换为下划线,生成唯一的可执行文件名
string(REPLACE "/" "_" EXECUTABLE_NAME ${REL_PATH})
string(REPLACE "\\" "_" EXECUTABLE_NAME ${EXECUTABLE_NAME})
string(REPLACE "." "_" EXECUTABLE_NAME ${EXECUTABLE_NAME})
# 处理与 CMakeLists.txt 文件同名的问题
if (${EXECUTABLE_NAME} STREQUAL "CMakeLists_txt")
set(EXECUTABLE_NAME "${EXECUTABLE_NAME}_exec")
endif ()
# 检查是否已经创建过同名的可执行文件
if (NOT EXECUTABLE_NAME IN_LIST EXECUTABLE_NAMES)
list(APPEND EXECUTABLE_NAMES ${EXECUTABLE_NAME})
# 创建可执行文件
add_executable(${EXECUTABLE_NAME} ${SOURCE})
# 查找源文件所在的目录,并添加为包含目录(头文件可能在同一目录下)
get_filename_component(DIR ${SOURCE} DIRECTORY)
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${DIR})
# 检查并添加子目录中的 include 目录(如果存在)
if (EXISTS "${DIR}/include")
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${DIR}/include)
endif ()
# 检查并添加 module 目录中的所有 C 文件(如果存在)
if (EXISTS "${DIR}/module")
file(GLOB_RECURSE MODULE_SOURCES "${DIR}/module/*.c")
target_sources(${EXECUTABLE_NAME} PRIVATE ${MODULE_SOURCES})
endif ()
endif ()
endforeach ()
```
## 7.4 配置 .clang-format 文件
* 配置 `.clang-format` 格式化文件,以便写代码的时候,可以自动保存并格式化 C 程序代码,如下所示:
![](./assets/155.png)
* `.clang-format` 的内容,如下所示:
```txt
BasedOnStyle: Google
IndentWidth: 4
UseTab: Never
ColumnLimit: 0
# 控制大括号的位置
BreakBeforeBraces: Attach
# 控制空行的使用
EmptyLineBeforeAccessModifier: Never
KeepEmptyLinesAtTheStartOfBlocks: true
# 控制短函数、短 if 语句和循环的格式
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
# 控制其他格式选项
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
# 控制注释的格式化
ReflowComments: true
# 控制包含指令的格式化
IncludeBlocks: Regroup
SortIncludes: CaseInsensitive
SpaceBeforeParens: ControlStatements
SpacesInParentheses: false
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
```
* CLion 中配置`保存`的时候`自动格式化`,即:
![](./assets/156.gif)
## 7.5 配置 .gitignore 文件
* 需要在项目中,配置 `.gitignore` 文件,以便在提交代码到 Git 仓库的时候,忽略某些文件或目录,如下所示:
![](./assets/157.png)
* `.gitignore` 文件的内容,如下所示:
```txt
.vscode
.idea
cmake-build-*
build
```
## 7.6 演示
* 我们可以在项目中,临时创建或复制一个文件,看上述配置是否生效,即:
> [!NOTE]
>
> 如果是复制并粘贴一个文件到项目中,请点击`重新加载 CMake 项目`
![](./assets/158.gif)
# 第八章C 语言的编译过程(⭐)
## 8.1 概述
* C 程序的编译过程,如下所示:
![](./assets/159.png)
* 过程 ① :编写(编辑)源代码,即:编写 C 语言源程序代码,并以文件的形式存储在磁盘中。
> [!IMPORTANT]
>
> 源程序需要以 `.c` 作为扩展名。
* 过程 ② :编译,即:将 C 语言源程序转换为`目标程序(或目标文件)`。如果程序没有错误,没有任何提示,就会生成一个扩展名为 `.obj``.o` 的二进制文件。C 语言中的每条可执行语句经过编译之后,最终都会转换为二进制的机器指令。
> [!IMPORTANT]
>
> * ① 其实,`编译阶段`包含了`预处理`、`编译`和`汇编`。
>
> * ② `预处理`是编译过程的第一个阶段。在这个阶段,预处理器处理源代码中的指令(例如:`#include`、`#define`等),主要任务包括:
>
> * **头文件包含**:将头文件的内容插入到源文件中。例如:`#include <stdio.h>`会被替换为`stdio.h`文件的内容。
> * **宏展开**:替换宏定义。例如:`#define PI 3.14`会将代码中的`PI`替换为`3.14`。
> * **条件编译**:根据条件指令(如:`#ifdef`、`#ifndef`)有选择地编译代码。
>
> * **删除代码中的注释,但是不会进行语法检查**。
>
> * 预处理完成后,生成一个扩展名为`.i`的中间文件。
>
> * ③ `编译`是将预处理后的源代码转换为汇编代码的过程。在这个阶段,编译器会检查代码的语法和语义,将其转换为目标机器的汇编语言,生成一个扩展名为`.s`的汇编文件。
>
> * ④ `汇编`是将汇编代码转换为机器代码(也称为目标代码或目标文件)的过程。在这个阶段,汇编器将汇编指令转换为二进制机器指令,生成一个扩展名为`.o`或 `.obj`的目标文件。
* 过程 ③ :链接(连接),即:将编译形成的目标文件 `*.obj``*.o`和库函数以及其他目录文件`链接`,形成一个统一的二进制文件 `*.exe`
>[!IMPORTANT]
>
>* 为什么需要链接库文件?
>* 因为我们的 C 程序会使用 C 程序库中的内容,如:`<stdio.h>` 中的 `printf()` 函数,这些函数不是程序员自己写的,而是 C 程序库中提供的因此需要链接。其实在链接过程中还会加入启动代码这个启动代码和系统相关Linux 下主要有 crt0.c、crti.c 等,它们设置堆栈后,再调用 main() 函数)负责初始化程序运行时的环境。
* 过程 ④ :执行,即:有了可执行的 `*.exe`文件,我们就可以在控制台上执行运行此 `*.exe` 文件。
> [!IMPORTANT]
>
> 如果`修改`了源代码,还需要重新`编译`、`链接`,并生成新的 `*.exe`文件,再执行,方能生效。
## 8.2 GCC 编译器的介绍
* 编辑器vim 、vscode 等,是指我们用它来编写源程序的(编辑代码),而我们写的代码语句,电脑是不懂的,我们需要把它转成电脑能懂的语句,编译器就是这样的转化工具。换言之,我们用编辑器编写程序,由编译器编译后才可以运行!
* 编译器是将易于编写、阅读和维护的高级计算机语言翻译为计算机能解读、运行的低级机器语言的程序。
* gccGNU Compiler CollectionGNU 编译器套件),是由 GNU 开发的编程语言编译器。gcc 原本作为 GNU 操作系统的官方编译器,现已被大多数类 Unix 操作系统Linux、BSD、Mac OS X 等采纳为标准的编译器gcc 同样适用于微软的 Windows 。
* gcc 最初用于编译 C 语言,随着项目的发展, gcc 已经成为了能够编译 C、C++、Java、Ada、fortran、Object C、Object C++、Go 语言的编译器大家族。
## 8.3 通过 gcc 直接生成可执行文件
* 示例:进行预处理、编译、汇编和链接
```shell
gcc HelloWorld.c -o HelloWorld.exe
```
![](./assets/160.gif)
## 8.4 通过 gcc 分步编译
### 8.3.1 概述
* 预处理命令:
```shell
gcc -E 源文件.c -o 源文件.i # 通常以 .i 结尾表示这个文件是一个中间状态
```
* 编译(预处理和编译)命令:
```shell
gcc -S 源文件.i -o 源文件.s # 在 Linux 中,通常以 .s 结尾;在 Windows 中,通常以 .asm 结尾
```
* 汇编(预处理、编译和汇编)命令:
```shell
gcc -c 源文件.s -o 源文件.o # 在 Linux 中,通常以 .o 结尾;在 Windows 中,通常以 .obj 结尾
```
* 链接(预处理、编译、汇编和链接)命令:
```shell
gcc 源文件.o -o 源文件.exe # 在 Linux 中,通常以 .out 结尾;在 Windows 中,通常以 .exe 结尾
```
### 8.4.2 应用示例
* 示例:只进行预处理
```shell
gcc -E HelloWorld.c -o HelloWorld.i
```
![](./assets/161.gif)
* 示例:只进行预处理和编译
```shell
gcc -S HelloWorld.i -o HelloWorld.s
```
![](./assets/162.gif)
* 示例:只进行预处理、编译和汇编
```shell
gcc -c HelloWorld.s -o HelloWorld.o
```
![](./assets/163.gif)
* 示例:进行预处理、编译、汇编和链接
```shell
gcc HelloWorld.o -o HelloWorld.exe
```
![](./assets/164.gif)
# 第九章:附录
## 9.1 WSL2 代理问题
* 在安装和配置 WSL2 之后,可能会出现如下的提示,即:
![](./assets/166.png)
* 那么,只需要修改 `%USERPROFILE%\.wslconfig`文件,内容如下:
```txt
[wsl2]
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
[experimental]
# requires dnsTunneling but are also OPTIONAL
bestEffortDnsParsing=true
useWindowsDnsCache=true
```
![](./assets/167.png)
* 在命令行中,执行如下的命令:
```shell
wsl --shutdown
```
![](./assets/168.gif)
* 此时,再打开终端,就没有这种提示了:
![](./assets/169.png)
## 9.2 CLion 调试问题
* 在 CLion 中进行 run运行程序的时候对于 `printf` 函数或 `scanf` 函数很正常,如下所示:
![](./assets/170.gif)
* 但是,当我们 debug调试 的时候,对于 `printf` 函数或 `scanf` 函数会一直没有输出,如下所示:
![](./assets/171.gif)
* 原因是 `scanf` 函数并不是直接让用户从键盘输入数据,而是先检查缓冲区,处理缓冲区中的数据;当遇到 `scanf` 函数时,程序会先检查输入缓冲区中是否有数据,所以解决方案就是`禁用缓冲区`,如下所示:
```c
#include <stdio.h>
int main() {
// 禁用 stdout 缓冲区
setbuf(stdout, NULL);
int a, b, c;
printf("请输入整数 a 、b 和 c 的值:");
scanf("%d %d %d", &a, &b, &c);
int result = a * b * c;
printf("%d × %d × %d = %d", a, b, c, result);
return 0;
}
```
* 那么,就会达到我们想要的效果了,如下所示:
![](./assets/172.gif)

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View File

@ -0,0 +1,1147 @@
# 第一章:变量(⭐)
## 1.1 程序中变化的数据
- 在生活中,我们使用最多的不是固定的数据,而是会变化的数据:
- ① 购物车商品的`数量`、`价格`等。
- ② 一首歌`播放的时间`、`进度条`、`歌词的展示`等。
- ③ 微信聊天中`消息条数`、`时间`、`语音的长度`、`头像`、`名称`等。
- ④ 游戏中技能的`冷却时间`、`血量`、`蓝量`、`buff 时间`、`金币的数量`等。
- ……
* 下图是一个`购物车`中`变化`的`数据`,即:
![](./assets/1.png)
* 那么,在实际开发中,我们就会使用`变量`来`保存`和`操作`这些`变化`的`数据`。
## 1.2 变量
* 变量的定义:变量是程序中不可或缺的组成单位,最基本的存储单元。其实,变量就是一个存储数据的临时空间,可以向其中存储不同类型的数据,如:整数、小数、字符、字符串等,并且变量中的数据在程序运行的时候可以动态改变。
> [!NOTE]
>
> * `变量`:用来`存储数据`的`容器`。
> * `数据`:可以是一个用来计算的`数字`,如:上文购物车中的`价格`等;也可以是一句话中的`关键词`或`其它任意格式的数据`。
> * 变量的`特别`之处就在于`它存放的数据是可以改变`的。
* 我们可以将`变量`想象为一个`容器`,盒子中`装的`就是我们想要的`数据`,并且我们需要`给`盒子`取`一个`特别的名称`;通过这个`特别的名称`,我们可以`给`盒子`添加数据`或`移除数据`,这个`特别的名称`就是`变量名`。
![](./assets/2.png)
> [!NOTE]
>
> * ① `变量`是内存中的一个`存储区域`,该区域的数据可以在`同一类型`范围内`不断变化`。
> * ② 通过`变量名`,可以`操作`这块内存区域,向其中`存储数据`或`获取数据`以及`移除数据`。
> * ③ 变量的构成包含三个要素:`数据类型`、`变量名`、`需要存储的数据`。
> * ④ 在生活中,我们会经常说:这件衣服的价格是 `100整型` 元,这双鞋子的价格是 `250.5(小数,浮点类型)` 元,`今天天气真好(字符串类型)`之类的话;在计算机科学中,这些都是数据,并且它们是有类型,即:数据类型。(数据类型用于定义变量所能存储的数据的种类以及可以对这些数据进行的操作的一种分类,每种数据类型都有特定的属性和用途,它们决定了变量在内存中如何表示和存储,以及变量可以执行哪些操作)
## 1.3 变量的声明和使用
* ① 变量必须先声明,后使用。
* ② 可以先声明变量再赋值,也可以在声明变量的同时进行赋值。
* ③ 变量的值可以在同一类型范围内不断变化。
>[!IMPORTANT]
>
>在实际开发中,我们通常都会在声明变量的同时,给其赋值,这被称为初始化。
* 示例:先声明,再使用
```c
#include <stdio.h>
int main() {
// 声明一个整型变量,取名为 a
int a;
// 给变量赋值
a = 10;
printf("a = %d\n", a);
return 0;
}
```
* 示例:初始化(声明变量的同时给其赋值)
```c
#include <stdio.h>
int main() {
// 声明一个整型变量,取名为 b ,并直接赋值(初始化,实际开发中最为常用)
int b = 200;
// 修改变量 b 的值,将变量 a 的值赋值给变量 b
b = 300;
printf("b= %d\n", b);
return 0;
}
```
* 示例:同时声明多个变量并赋值
```c
#include <stdio.h>
int main() {
// 同时声明多个整型的变量并赋值
int c1 = 10, c2 = 20, c3 = 30;
printf("c1 = %d\n", c1);
printf("c2 = %d\n", c2);
printf("c3 = %d\n", c3);
return 0;
}
```
## 1.4 从计算机底层看变量
### 1.4.1 内存条的内部结构
* 如果只看内存条的外观,无非就是一些集成电路和颗粒而已,如下所示:
![](./assets/3.jpeg)
* 并且,我们只需要将内存条插入到计算机主板对应的内存条插槽上,就可以正常工作,如下所示:
![](./assets/4.jpg)
* 在家用的台式机主板上,通常有 4 个插槽或 2 个插槽,例如:本人的计算机就支持 4 个插槽,如下所示:
![](./assets/5.png)
>[!NOTE]
>
>* ① 上图中的外形规格是 DIMM所以我们通常也以 DIMM 也表示内存条。
>* ② DIMM 是内存条的物理形式,安装在主板的内存插槽中。
>* ③ 常见的 DIMM 类型包括 UDIMM非缓冲 DIMM、RDIMM缓冲 DIMM和 LRDIMM负载减少DIMM
* 我们可以通过 [CPU-Z](https://www.cpuid.com/) 这个软件,查看 CPU 的一些指标信息,如下所示:
![](./assets/6.png)
> [!NOTE]
>
> * ① 通过 CPU-Z 表明本人的台式机是支持双通道的,`channel` 在`计算机`中可以`翻译`为`信道`或`通道`。
> * ② 通道是内存控制器与内存模块之间的通信路径。
> * ③ 多通道内存可以提高数据传输带宽。例如:双通道内存系统同时使用两个通道来传输数据,从而提高性能。
> * ④ 现代主板通常支持双通道Dual Channel、四通道Quad Channel甚至八通道Octa Channel
* 对于家用台式机而言,如果将内存条的插槽从左到右依次编号,如下所示:
![](./assets/7.png)
* 其中,`槽1` 和 `槽2` 是一个通道,`槽3` 和 `槽4` 是一个通道;所以,通常是这么建议的:
* 如果只有 1 根内存条,就插到 `槽2` 中。
* 如果有 2 根内存条,就分别插入到 `槽2``槽4` 中。
* 如果有 4 根内存条,就全插满即可。
> [!NOTE]
>
> 组成双通道配置的内存条需要遵循一些基本要求来确保它们能够正常以双通道模式运行:
>
> - ① **相同容量**:理想情况下,组成双通道的内存条应该具有相同的容量。这样可以确保它们在处理数据时的一致性和兼容性。
> - ② **匹配的速度规格**内存条应该具有相同的速度规格即它们的频率DDR4-2400、DDR4-3200等应该相同。不同速度的内存条可以一起工作但系统会以所有内存条中最慢的那个的速度运行。
> - ③ **相同的时序**内存条的时序CL16-18-18-38应该匹配。时序参数影响内存的响应速度和稳定性不匹配的时序可能会降低性能或导致系统不稳定。
> - ④ **相同的制造商和型号**(推荐):虽然不是强制性要求,但选择相同制造商和型号的内存条可以最大限度地减少兼容性问题。不同制造商的内存条可能在微小的规格和性能上有差异,这有可能影响双通道配置的效能。
* 内存条表面会有内存颗粒,如下所示:
![](./assets/8.png)
> [!NOTE]
>
> 上图中的内存条有 8 个内存颗粒;但是,高端服务器上的内存条通常会存在 9 个内存颗粒,最后 1 个内存颗粒专门用来做 ECC 校验。
* 一个内存条有两面,高端的内存条两面都有内存颗粒,我们将每个面称为 Rank 。那么,如果内存条有两个面,就是存在 Rank0 和 Rank1 ,即:
![](./assets/9.png)
* 内存条表面的黑色颗粒,我们称为 chip芯片 ,即:
![](./assets/10.png)
> [!NOTE]
>
> * ① 内存颗粒是内存条上的 DRAM 芯片,每个芯片包含多个存储单元。
> * ② 内存颗粒存储数据并与内存控制器进行数据交换。
* 在 chip 中还有 8 个 bank每个 bank 就是数据存储的实体,这些 bank 组成了一个二维矩阵,只要声明了 column 和 row 就可以从每个 bank 中取出 8bit 1 Bytes的数据如下所示
![img](./assets/11.png)
* 综上所示,内存条的分层结构就是 `Channel > DIMM > Rank -> Chip -> Bank -> Row/Column`
### 1.4.2 变量的作用
* 如果我们希望计算 10 和 20 的和;那么,在计算机中需要怎么做?
* ① 首先,计算 10 和 20 的运算,一定在 CPU 中进行,因为在计算机中的各个部件中,只有 CPU 有运算器ALU
* ② 其次,我们需要将 10 和 20 交给 CPU ;由于 CPU 只能和内存进行交互,那么我们必须将 10 和 20 存储到内存中。
> [!NOTE]
>
> 即使 10 和 20 是存储在文件中的,也需要先加载进内存,然后再交给 CPU 进行运算。
* ③ 最后,只需要告诉 CPU 做何种运算,如:加、减、乘、除等。
* 其中,最为重要的问题就是如何将数据存储到内存中?答案就是通过`变量`。
![](./assets/12.png)
* 我们知道,计算机底层是使用二进制来表示指令和数据的;但是,如果我们的代码都是这样的,即:
```txt
0000,0000,000000010000 代表 LOAD A, 16
0000,0001,000000000001 代表 LOAD B, 1
0001,0001,000000010000 代表 STORE B, 16
```
* 这样,直接使用`内存地址`来编写代码(机器语言)实现是太难阅读、修改和维护了;于是,我们就使用了汇编语言来编写代码,并通过编译器来将汇编语言翻译为机器语言,即:
```txt
LOAD A, 16 -- 编译 --> 0000,0000,000000010000
LOAD B, 1 -- 编译 --> 0000,0001,000000000001
STORE B, 16 -- 编译 --> 0001,0001,000000010000
```
* 但是,这样的汇编语言还是面向机器的,编程时仍然需要记住和管理大量内存地址,不具备程序的移植性;于是,我们就是使用了高级语言来编写代码,并引入了变量的概念,即:
```c
int num = 10;
```
* 我们使用`变量名`来`关联`内存`地址`,这样我们在编写代码的时候,就可以不用直接操作内存地址,极大地提高了代码的可读性和开发效率。并且,当程序运行完毕之后,程序所占用的内存还会交还给操作系统,以便其它程序使用。
* 综上所述,高级语言编译器的作用就是:
* ① 编写源代码时使用变量名。
* ② 程序在经过编译器的编译之后,所有变量名被替换为具体地址。
* ③ ……
* 此时,我们就可以知道,`变量`就是内存中用于`存储数据`的`临时空间`,并且变量中的值是可以变化的。
* `内存`中空间的`最小单位`是`字节`Bytes即 8 个 0 或 1 ,如下所示:
```txt
00011001 00100110 00100110 00100110 00100110 ...
```
> [!NOTE]
>
> 计算机中存储单位的换算,如下所示:
>
> * 1 B = 8 bit。
> * 1 KB = 1024 B。
> * 1 MB = 1024 KB。
> * 1 GB = 1024 MB。
> * 1 TB = 1024 GB 。
> * ……
* 在内存中,每一个字节都有一个编号,这个编号我们称之为地址。一个变量至少占用 1 个字节1 个或多个字节我们将变量的第一个字节所占用的地址变量的首地址就称之为该变量的地址。CPU 就可以通过变量地址找到某个变量的值,然后拿到具体的数据进行计算了。
> [!NOTE]
>
> 变量就是保存程序运行过程中临时产生的值。
* 其实,到这里还是有疑惑的?我们说过,一个变量至少会占用 1 个字节,如果一个变量占用了 4 个字节,而 CPU 只会通过变量的地址(首地址)获取数据,那么 CPU 是如何获取完整的数据的?答案就是通过`数据类型`,数据类型除了限制数据的种类,还限制了数据在内存中所占空间的大小,如上图所示:
* ① 假设变量 `a` 的首地址是 `01` ,变量的数据类型是 `4` 个字节。
* ② 那么CPU 就会依次,从 `01 ~ 04` 中获取数据。
* 再次,剖析下变量的语法格式:
```txt
数据类型 变量名 = 值;
```
* `变量名`的`作用`,如下所示:
* ① 当我们`编写`代码的时候,使用`变量名`来`关联`某块内存的`地址`。
* ② 当 CPU `执行`的时候,会将变量名`替换`为具体的地址,再进行具体的操作。
> [!CAUTION]
>
> 变量名(标识符)需要符合命名规则和命名规范!!!
* `数据类型`的`作用`,如下所示:
* ① 变量的数据类型`决定了`变量所占空间的大小。当我们在声明变量的时候写了数据数据类型CPU 就知道从变量的首地址位置开始取多少字节。
* ② 变量的数据类型`决定了`两个变量是否能够运行以及能够做何种运算。例如JavaScript 就没有 char 类型的变量,都是 string 类型,可以和任意数据类型的数据拼接,并转换为 string 类型Java 中有 char 类型的变量,底层都会转换 unicode 编码,然后再计算。
* `值`的`作用`,如下所示:
* ① `值`就是`内存`中`实际存储`的`数据`。
* ② `=` 是赋值操作符,就是将等号右侧的数据存储到等号左侧的变量名所代表的内存空间。
* 那么,如下代码的含义就是:
```c
// int 数据类型4 个字节
// num 变量名 -- 关联内存中的一块存储空间
// = 10 将 10 存储到 num 所代表的 4 个字节的存储空间中
int num = 10;
```
## 1.6 变量的重要操作
### 1.6.1 变量的输出
* 在计算机中,所谓的`输入`和`输出`都是以计算机CPU 和内存)为主体而言的,即:
>[!NOTE]
>
>输入:从输入设备(键盘、鼠标、扫描仪)向计算机输入数据。
>
>输出:从计算机向外部输出设备(显示器、打印机)输出数据。
![](./assets/13.png)
* 在 C 语言中,提供了 `printf()` 函数用于输出信息,其函数声明是:
```c
int printf (const char *__format, ...) {
...
}
```
* `printf` 的标准含义是格式化输出文本,来源于 `print formatted格式化打印`的缩写,其语法规则,如下所示:
![](./assets/14.png)
> [!NOTE]
>
> * 格式化字符串:是使用双引号括起来的字符串,里面包含了普通的字符串和格式占位符。
> * 格式占位符(格式声明符):由 `%` 和`格式字符`组成,作用是将输出的数据转换为指定的格式后输出,这里的 `%d` 表示整数。
> * 输出列表:是程序要输出的一些数据,可以是常量、变量或表达式,需要和格式占位符一一对应。
* 在计算机中,二进制、八进制、十进制以及十六进制的英文名称和缩写,如下所示:
* 二进制binary缩写是 bin。
* 八进制octal缩写是 oct。
* 十进制decimal缩写是 dec。
* 十六进制Hexadecimal缩写是 hex。
* 其实,我们也可以在 Windows 系统中的计算器中来看到,即:
![](./assets/15.png)
> [!IMPORTANT]
>
> 在生活中的 decimal 是小数的意思但是在计算机中decimal 的完整含义是 decimal integer ,即十进制整数。
* 示例:
```c
#include <stdio.h>
int main() {
// 声明变量并赋值
int num = 18;
// 使用输出语句,将变量 num 的值输出,其中 %d 表示输出的是整数
printf("我今年%d岁\n", num);
return 0;
}
```
### 1.6.2 计算变量的大小
* 我们可以使用 `sizeof`关键字(运算符)来计算变量或类型所占内存空间的大小。
* 示例:
```c
#include <stdio.h>
int main() {
int num = 10;
printf("变量所占内存空间的大小:%zd字节\n", sizeof(num));
// 数据类型所占内存空间的大小
printf("数据类型所占内存空间的大小:%zd字节\n", sizeof(int));
return 0;
}
```
### 1.6.3 获取变量的地址
* 在 C 语言中,我们可以使用`取地址运算符 &` 来获取变量的地址。
* 示例:
```c
#include <stdio.h>
int main() {
int num = 10;
printf("变量 num 的值是:%d\n", num);
printf("变量 num 的地址(指针)是:%#p\n", &num);
return 0;
}
```
### 1.6.4 变量的输入
* 在 C 语言中,提供了 `scanf()` 函数用于从标准输入(通常是键盘)中读取数据并根据变量的地址赋值给变量(变量需要提前声明),其函数声明是:
```c
int scanf(const char *__format, ...) {
...
}
```
* 其语法规则,如下所示:
![](./assets/16.png)
> [!NOTE]
>
> `&age`、`&num` 中的 `&`是寻址操作符,`&age` 表示变量 `age` 在内存中的地址。
> [!CAUTION]
>
> * ① scanf() 函数中的 `%d`,如果是连着写,即:`%d%d`,那么在输入数据的时候,数据之间不可以使用逗号`,`分隔只能使用空白字符空格、tab 键或回车键),即:`2空格3tab`或`2tab3回车`等。
>
> * ② 如果是 `%d,%d`,则输入的时候需要加上逗号`,`,即:`2,3`。
> * ③ 如果是 `%d %d`,则输入的时候需要加上空格,即:`2空格3`。
* 示例:计算圆的面积,半径由用户指定
```c
#include <stdio.h>
int main() {
// 禁用 stdout 缓冲区
// CLion debug 独有,后文不再提及,如果 debug 有问题,就添加如下代码
setbuf(stdout, NULL);
float radius;
printf("请输入一个半径:");
scanf("%f", &radius);
double area = 3.1415926 * radius * radius;
printf("半径是%f的圆的面积是%.2lf", radius, area);
return 0;
}
```
* 示例:输入一个整数值,求其绝对值
```c
#include <stdio.h>
int main() {
int num;
printf("请输入一个整数:");
scanf("%d", &num);
int absNum;
if (num < 0) {
absNum = -num;
} else {
absNum = num;
}
printf("%d的绝对值是%d", num, absNum);
return 0;
}
```
* 示例:输入多个变量的值,求其乘积
```c
#include <stdio.h>
int main() {
int a, b, c;
printf("请输入整数 a 、b 和 c 的值:");
scanf("%d %d %d", &a, &b, &c);
int result = a * b * c;
printf("%d × %d × %d = %d", a, b, c, result);
return 0;
}
```
## 1.7 标识符
### 1.7.1 概述
* 在 C 语言中,变量、函数、数组名、结构体等要素命名的时候使用的字符序列,称为标识符。
> [!NOTE]
>
> 在上世纪 60 - 70 年代的时候,因为国家贫穷,人民生活不富裕等原因,家长虽然会给孩子取名为:`张建国`、`李华强`等;但是,也会取小名为`二狗子`、`狗剩`等,目的是希望孩子能健康成长(养活),像 `张建国`、`李华强`、`二狗子`、`狗剩`都是名字(标识符),伴随人的一生。
### 1.7.2 标识符的命名规范
* 强制规范:
* ① 只能由`小写`或`大写英文字母``0-9` 或 `_` 组成。
* ② 不能以`数字`开头。
* ③ 不可以是`关键字`。
* ④ 标识符具有`长度`限制,不同编译器和平台会有所不同,一般限制在 63 个字符内。
* ⑤ 严格`区分大小写字母`Hello、hello 是不同的标识符。
* 建议规范:
* ① 为了提高阅读性使用有意义的单词见名知意sumnamemaxyear 等。
* ② 使用下划线连接多个单词组成的标识符max_classes_per_student 等。
* ③ 多个单词组成的标识符,除了使用下划线连接,也可以使用小驼峰命名法,除第一个单词外,后续单词的首字母大写,如: studentId、student_name 等。
* ④ 不要出现仅靠大小写区分不同的标识符name、Name 容易混淆。
* ⑤ 系统内部使用了一些下划线开头的标识符C99 标准添加的类型 `_Bool`,为防止冲突,建议开发者尽量避免使用下划线开头的标识符。
* 示例:合法(不一定建议)的标识符
```txt
a、BOOK_sun、MAX_SIZE、Mouse、student23、Football、FOOTBALL、max、_add、num_1、sum_of_numbers
```
* 示例:非法的标识符
```txt
$zj、3sum、ab#cd、23student、Foot-baii、s.com、bc、j**p、book-1、tax rate、don't
```
### 1.7.3 关键字
* C 语言中的关键字是编译器`预定义`的`保留字`,它们有`特定`的`含义`和`用途`,用于控制程序的结构和执行。
* C80 和 C90 ANSI C定义的关键字如下所示
| 类型(功能) | 具体关键字 |
| -------------------------- | ------------------------------------------------------------ |
| 数据类型关键字 | `char`、`double`、`float`、`int`、`long`、`short`、`signed`、`unsigned`、`void` |
| 存储类说明符关键字 | `auto`、`extern`、`register`、`static`、`typedef`、`volatile`、`const` |
| 控制语句关键字 | `break`、`case`、`continue`、`default`、`do`、`else`、`for`、`goto`、`if`、`return`、`switch`、`while` |
| 结构体、联合体和枚举关键字 | `enum`、`struct`、`union` |
| 其他关键字 | `sizeof` |
* C99 新增的关键字,如下所示:
| 类型(功能) | 具体关键字 |
| ------------------ | --------------------------------- |
| 数据类型关键字 | `_Bool`、`_Complex`、`_Imaginary` |
| 存储类说明符关键字 | `inline`、`restrict` |
| 其他关键字 | `_Complex``_Imaginary` |
* C11 新增的关键字,如下所示:
| 类型(功能) | 具体关键字 |
| ------------------ | ------------------------------------------------------------ |
| 存储类说明符关键字 | `_Atomic` |
| 其他关键字 | `_Alignas``_Alignof``_Generic``_Noreturn``_Static_assert``_Thread_local` |
> [!IMPORTANT]
>
> * ① 关键字不能用作标识符(如:变量名、函数名等)。
> * ② 不要死记硬背这些关键字,在实际开发中,并不一定全部使用到;而且,在学到后面的时候,会自动记住这些关键字以及对应的含义。
# 第二章:常量(⭐)
## 2.1 概述
* 在程序运行过程中,不能改变的量就是常量。
>[!NOTE]
>
>* ① 在数学中的 `π`,就是一个常量,其值为 3.1415926 。
>* ② 在生活中,人类的性别只有`男`和`女`;其中,`男`和`女`也是常量。
>* ③ ...
## 2.2 常量的分类
* 在 C 语言中的变量的分类,如下所示:
* ① 字面量常量。
* ② 标识符常量:
* `#define` 宏定义的标识符常量。
* `const` 关键字修饰的标识符常量。
* 枚举常量。
>[!NOTE]
>
>* 所谓的`字面量常量`,就是可以直接使用的常量,不需要声明或定义,包括:整数常量、浮点数常量以及字符常量。
>* 所谓的`标识符常量`,就是使用标识符来作为常量名,包括: `#define` 宏定义的标识符常量、`const` 关键字修饰的标识符常量、枚举常量。
* 示例:字面量常量
```c
#include <stdio.h>
int main() {
1;
'A';
12.3;
"你好";
return 0;
}
```
* 示例:字面量常量
```c
#include <stdio.h>
int main() {
printf("整数常量 =》%d\n", 1);
printf("字符常量 =》%c\n", 'A');
printf("浮点数常量 =》%f\n", 12.3);
printf("字符串常量 =》%s\n", "你好");
return 0;
}
```
## 2.3 使用 #define 定义常量
* `#define` 来定义常量,也叫作宏定义,就是用一个标识符来表示一个常量值,如果在后面的代码中出现了该标识符,那么编译时就全部替换成指定的常量值,即用宏体替换所有宏名,简称`宏替换`。
* 格式是:
```c
#define 常量名 常量值
```
> [!CAUTION]
>
> * ① 其实`宏定义`的常量的`执行时机`是在`预处理`阶段,将所有`宏常量`替换完毕,才会继续编译代码。
> * ② 不要以 `;` 结尾,如果有 `;` ,分号也会成为常量值的一部分。
> * ③ `# define` 必须写在 `main` 函数的外面!!!
> * ④ `常量名`习惯用`大写字母`表示,如果多个单词,使用 `_` 来分隔,以便和变量区分。
* 示例:
```c
#include <stdio.h>
#define PI 3.1415926
int main() {
double radius = 2.5;
double area = PI * radius * radius;
printf("半径为%lf的圆的面积是%.2lf", radius, area);
return 0;
}
```
## 2.4 const 关键字
* C99 标准新增,这种方式跟定义一个变量是类似的;只不过,需要在变量的数据类型前加上 `const` 关键字。
* 和使用 `#define定义宏常量`相比const 定义的常量有详细的数据类型,而且会在编译阶段进行安全检查,在运行时才完成替换,所以会更加安全和方便。
* 格式是:
```c
const 数据类型 常量名 = 常量值;
```
* 示例:
```c
#include <stdio.h>
const int PI = 3.1415926;
int main() {
double radius = 2.5;
double area = PI * radius * radius;
printf("半径为%lf的圆的面积是%.2lf", radius, area);
return 0;
}
```
## 2.5 枚举常量
* 格式:
```c
enum 枚举常量 {
xxx = 1;
yyy;
...
}
```
> [!NOTE]
>
> * ① 默认情况下,枚举常量是从 0 开始递增的。
> * ② 也可以在定义枚举常量的时候,自定义它们的值。
* 示例:
```c
#include <stdio.h>
enum sex {
MALE = 1,
FEMALE = 2,
};
int main() {
printf("%d\n", MALE);
printf("%d\n", FEMALE);
return 0;
}
```
* 示例:
```c
#include <stdio.h>
enum Sex {
MALE = 1,
FEMALE = 2,
};
int main() {
enum Sex sex;
printf("请输入性别(1 表示男性, 2 表示女性)");
scanf("%d", &sex);
printf("您的性别是:%d\n", sex);
return 0;
}
```
## 2.6 #defind 定义常量 VS const 定义常量
* ① 执行时机:`#define` 是预处理指令,在编译`之前`执行;`const` 是关键字,在编译`过程`中执行。
* ② 类型检查:`#define` 定义常量`不用指定类型``不进行类型检查`,只是简单地文本替换;`const` 定义常量`需要指定数据类型``会进行类型检查`,类型安全性更强。
# 第三章:二进制
## 3.1 概述
* 计算机的底层只有`二进制`,即计算机中`运算`和`存储`的`所有数据`都需要转换为`二进制`,包括:数字、字符、图片、视频等。
![](./assets/17.jpg)
* 之前,我们也提到现代的计算机(量子计算机除外)几乎都遵循`冯·诺依曼`体系结构,其理论要点如下:
* ① **存储程序**`程序指令`和`数据`都存储在计算机的内存中,这使得程序可以在运行时修改。
* ② **二进制逻辑**:所有数据和指令都以`二进制`形式表示。
* ③ **顺序执行**:指令按照它们在内存中的顺序执行,但可以有条件地改变执行顺序。
* ④ **五大部件**:计算机由`运算器`、`控制器`、`存储器`、`输入设备`和`输出设备`组成。
* ⑤ **指令结构**:指令由操作码和地址码组成,操作码指示要执行的操作,地址码指示操作数的位置。
* ⑥ **中心化控制**计算机的控制单元CPU负责解释和执行指令控制数据流。
* 所以,再次论证了为什么计算机只能识别二进制。
## 3.2 进制
### 3.2.1 常见的进制
* 在生活中,我们最为常用的进制就是`十进制`,其规则是`满 10 进 1` ,即:
![](./assets/18.jpeg)
* 在计算机中,常见的进制有`二进制`、`八进制`和`十六进制`,即:
* 二进制:只能 0 和 1 ,满 2 进 1 。
* 八进制0 ~ 7 ,满 8 进 1 。
* 十六进制0 ~ 9 以及 A ~ F ,满 16 进 1 。
> [!NOTE]
>
> 在十六进制中,除了 0 到 9 这十个数字之外,还引入了字母,以便表示超过 9 的值。字母 A 对应十进制的 10 ,字母 B 对应十进制的 11 ,以此类推,字母 F 对应十进制的 15。
* 进制的换算举例,如下所示:
| 十进制 | 二进制 | 八进制 | 十六进制 |
| ------ | ------ | ------ | -------- |
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 |
| 2 | 10 | 2 | 2 |
| 3 | 11 | 3 | 3 |
| 4 | 100 | 4 | 4 |
| 5 | 101 | 5 | 5 |
| 6 | 110 | 6 | 6 |
| 7 | 111 | 7 | 7 |
| 8 | 1000 | 10 | 8 |
| 9 | 1001 | 11 | 9 |
| 10 | 1010 | 12 | a 或 A |
| 11 | 1011 | 13 | b 或 B |
| 12 | 1100 | 14 | c 或 C |
| 13 | 1101 | 15 | d 或 D |
| 14 | 1110 | 16 | e 或 E |
| 15 | 1111 | 17 | f 或 F |
| 16 | 10000 | 20 | 10 |
| ... | ... | ... | ... |
* 二进制和十六进制的关系:十六进制是以 16 为基数的进制系统16 在二进制中表示为 ( 2^4 ),即:一个十六进制可以表示 4 位二进制。
> [!NOTE]
>
> 十六进制的范围是0 ~ F 0 ~ 15对应的二进制数的范围是0000 ~ 1111 0 ~ 15
* 每个十六进制数都可以映射到一个唯一的 4 位二进制数,即:
| 十六进制 | 二进制 |
| -------- | ------ |
| 0 | 0000 |
| 1 | 0001 |
| 2 | 0010 |
| 3 | 0011 |
| 4 | 0100 |
| 5 | 0101 |
| 6 | 0110 |
| 7 | 0111 |
| 8 | 1000 |
| 9 | 1001 |
| A | 1010 |
| B | 1011 |
| C | 1100 |
| D | 1101 |
| E | 1110 |
| F | 1111 |
>[!NOTE]
>
>由此可见,每个十六进制数字确实由 4 位二进制数表示。
* 二进制和八进制的关系:八进制是以 8 为基数的进制系统8 在二进制中表示为 ( 2^3 );即:一个八进制位可以表示 3 个二进制位。
> [!NOTE]
>
> 八进制的范围是0 ~ 7 对应的二进制数的范围是000 ~ 111。
* 每个八进制数位都可以映射到一个唯一的 3 位二进制数,即:
| 八进制 | 二进制 |
| ------ | ------ |
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| 4 | 100 |
| 5 | 101 |
| 6 | 110 |
| 7 | 111 |
> [!NOTE]
>
> 由此可见,每个八进制数字确实由 3 位二进制数表示。
### 3.2.2 C 语言中如何表示不同进制的整数?
* 规则如下:
* 在 C 语言中,如果是`二进制`(字面常量),则需要在二进制整数前加上 `0b``0B`
* 在 C 语言中,如果是`八进制`(字面常量),则需要在八进制整数前加上 `0`
* 在 C 语言中,如果是`十进制`(字面常量),正常数字表示即可。
* 在 C 语言中,如果是`十六进制`(字面常量),则需要在十六进制整数前加上 `0x`或`0X` 。
* 示例:
```c
#include <stdio.h>
int main() {
int num1 = 0b10100110; // 二进制
int num2 = 0717563; // 八进制
int num3 = 1000; // 十进制
int num4 = 0xaf72; // 十六进制
printf("num1 = %d\n", num1); // num1 = 166
printf("num2 = %d\n", num2); // num2 = 237427
printf("num3 = %d\n", num3); // num3 = 1000
printf("num4 = %d\n", num4); // num4 = 44914
return 0;
}
```
### 3.2.3 输出格式
* 在 C 语言中,可以使用不同的`格式占位符`来`输出`不同`进制`的整数,如下所示:
* `%d`:十进制整数。
* `%o` :八进制整数。
* `%x`:十六进制整数。
* `%#o` :显示前缀 `0` 的八进制整数。
* `%#x` :显示前缀 `0x` 的十六进制整数。
* `%#X` :显示前缀 `0X` 的十六进制整数。
> [!CAUTION]
>
> C 语言中没有输出二进制数的格式占位符!!!
* 示例:
```c
#include <stdio.h>
int main() {
int num = 100;
printf("%d 的十进制整数: %d\n", num, num); // 100 的十进制整数: 100
printf("%d 的八进制整数: %o\n", num, num); // 100 的八进制整数: 144
printf("%d 的十六进制整数: %x\n", num, num); // 100 的十六进制整数: 64
printf("%d 的八进制(前缀)整数: %#o\n", num, num); // 100 的八进制(前缀)整数: 0144
printf("%d 的十六进制(前缀)整数: %#x\n", num, num); // 100 的十六进制(前缀)整数: 0x64
printf("%d 的十六进制(前缀)整数: %#X\n", num, num); // 100 的十六进制(前缀)整数: 0X64
return 0;
}
```
## 3.3 进制的转换
### 3.3.1 概述
* 不同进制的转换,如下所示:
![](./assets/19.png)
* 在计算机中,数据是从右往左的方式排列的;其中,最右边的是低位,最左边的是高位,即:
![](./assets/20.png)
### 3.3.2 二进制和十进制的转换
#### 3.3.2.1 二进制转换为十进制
* 规则:从最低位开始,将每个位上的数提取出来,乘以 2 的 (位数 - 1 )次方,然后求和。
> [!NOTE]
>
> * ① 在学术界,将这种计算规则,称为`位权相加法`。
> * ② `八进制转换为十进制`、`十六进制转换为十进制`和`二进制转换为十进制`的算法相同!!!
* 示例:十进制转十进制
![](./assets/21.png)
* 示例:二进制转十进制
![](./assets/22.png)
#### 3.3.2.2 十进制转换二进制
* 规则:将该数不断除以 2 ,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制。
> [!NOTE]
>
> * ① 在学术界,将这种计算规则,称为`短除法`或`连续除2取余法`。
> * ② 很好理解,只有不断地除以 2 ,就能保证最大的数字不超过 2 ,这不就是二进制(只能有 0 或 1
> * ③ `八进制转换为二进制`、`十六进制转换为二进制`和`十进制转换为二进制`的算法相同!!!
* 示例:十进制转十进制
![](./assets/23.png)
* 示例:十进制转二进制
![](./assets/24.png)
### 3.3.3 二进制转八进制
* 规则:每 3 位二进制就是一个八进制。
* 示例011 101 001 -> 351
![](./assets/25.png)
### 3.3.4 二进制转十六进制
* 规则:每 4 位二进制就是一个十六进制。
* 示例1110 1001 -> 0xE9
![](./assets/26.png)
## 3.4 原码、反码和补码
### 3.4.1 概述
* 机器数一个数在计算机的存储形式是二进制我们称这些二进制数为机器数。机器数可以是有符号的用机器数的最高位来存放符号位0 表示正数1 表示负数。
![](./assets/27.png)
* 真值:因为机器数带有符号位,所以机器数的形式值不等于其真实表示的值(真值),以机器数 1000 0001 为例,其真正表示的值(首位是符号位)为 -1而形式值却是 129 ,因此将带有符号位的机器数的真正表示的值称为机器数的真值。
![](./assets/28.png)
### 3.4.2 原码
* 原码的表示与机器数真值表示的一样,即用第一位表示符号,其余位表示数值。
* 规则:
* 正数的`原码`是它本身对应的二进制数,符号位是 0 。
* 负数的`原码`是它本身绝对值对应的二进制数,但是符号位是 1 。
* +1 的原码,使用 8 位二进数来表示,就是:
| 十进制数 | 原码8位二进制数 |
| -------- | ------------------- |
| +1 | `0`000 0001 |
* -1 的原码,使用 8 位二进数来表示,就是:
| 十进制数 | 原码8位二进制数 |
| -------- | ------------------- |
| -1 | `1`000 0001 |
> [!IMPORTANT]
>
> 按照原码的规则,会出现 `+0``-0` 的情况,即:`0`000 0000+0、`1`000 0000-0显然不符合实际情况所以计算机底层虽然存储和计算的都是二进数但显然不是原码。
### 3.4.3 反码
* 规则:
* 正数的反码和它的原码相同。
* 负数的反码是在其原码的基础上,符号位不变,其余各位取反。
* +1 的反码,使用 8 位二进数来表示,就是:
| 十进制数 | 原码8位二进制数 | 反码8位二进制数 |
| -------- | ------------------- | ------------------- |
| +1 | `0`000 0001 | `0`000 0001 |
* -1 的反码,使用 8 位二进数来表示,就是:
| 十进制数 | 原码8位二进制数 | 反码8位二进制数 |
| -------- | ------------------- | ------------------- |
| -1 | `1`000 0001 | `1`111 1110 |
> [!IMPORTANT]
>
> 按照反码的规则,如果是 `+0`,对应的原码是 `0`000 0000那么其反码还是 `0`000 0000 ;如果是 `-0`,对应的原码是 `1`000 0000其反码是 `1`111 1111显然不符合实际情况所以计算机底层虽然存储和计算的都是二进数但显然不是反码。
### 3.4.4 补码
* 规则:
* 正数的补码和它的原码相同。
* 负数的补码是在其反码的基础上 + 1 。
* +1 的补码,使用 8 位二进数来表示,就是:
| 十进制数 | 原码8位二进制数 | 反码8位二进制数 | 补码8位二进制数 |
| -------- | ------------------- | ------------------- | ------------------- |
| +1 | `0`000 0001 | `0`000 0001 | `0`000 0001 |
* -1 的补码,使用 8 位二进数来表示,就是:
| 十进制数 | 原码8位二进制数 | 反码8位二进制数 | 补码8位二进制数 |
| -------- | ------------------- | ------------------- | ------------------- |
| -1 | `1`000 0001 | `1`111 1110 | `1`111 1111 |
* 如果 0 ,按照 `+0` 的情况进行处理,即:
![](./assets/29.png)
* 如果 0 ,按照 `-0` 的情况进行处理,即:
![](./assets/30.png)
> [!IMPORTANT]
>
> * ① 补码表示法解决了`原码`和`反码`存在的`两种`零(`+0` 和 `-0`)的问题,即:在补码表示法中,只有`一个`零,即 0000 0000。
> * ②补码使得`加法运算`和`减法运算`可以统一处理,通过将减法运算`转换`为加法运算,可以简化硬件设计,提高了运算效率。
> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。
### 3.4.5 总结
* ① 正数的原码、反码和补码都是一样的,三码合一。
* ② 负数的反码是在其原码的基础上按位取反0 变 1 1 变 0 ),符号位不变;负数的补码是其反码 + 1 。
* ③ 0 的补码是 0 。
## 3.5 计算机底层为什么使用补码?
* 如果计算是 `2 - 2` ,那么可以转换为 `2 + (-2)`,这样计算机内部在处理`减法计算`的时候,就会将其转换为`加法计算`的形式,以简化硬件设计和提高计算效率。
* `最高位`表示`符号位`,由于符号位的存在,如果使用`原码`来计算,就会导致`计算结果不正确`,即:
![](./assets/31.png)
* `补码`的设计可以巧妙的让`符号位`也参与计算,并且可以得到`正确的计算结果`,即:
![](./assets/32.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 KiB

View File

@ -0,0 +1,2083 @@
# 第一章:数据类型(⭐)
## 1.1 概述
* 根据`变量`中`存储`的`值`的`不同`,我们可以将`变量`分为两类:
* `普通变量`:变量所对应的内存中存储的是`普通值`。
* `指针变量`:变量所对应的内存中存储的是`另一个变量的地址`。
* 如下图所示:
![](./assets/1.png)
> [!NOTE]
>
> 普通变量和指针变量的相同点:
>
> * 普通变量有内存空间,指针变量也有内存空间。
> * 普通变量有内存地址,指针变量也有内存地址。
> * 普通变量所对应的内存空间中有值,指针变量所对应的内存空间中也有值。
>
> 普通变量和指针变量的不同点:
>
> * 普通变量所对应的内存空间存储的是普通的值,如:整数、小数、字符等;指针变量所对应的内存空间存储的是另外一个变量的地址。
> * 普通变量有普通变量的运算方式,而指针变量有指针变量的运算方式(后续讲解)。
* 那么,在 C 语言中变量的数据类型就可以这么划分,如下所示:
![](./assets/2.png)
> [!NOTE]
>
> * 根据`普通变量`中`存储`的`值`的类型不同,可以将`普通变量类型`划分为`基本数据类型`(整型、字符类型、浮点类型、布尔类型)和`复合数据类型`(数组类型、结构体类型、共用体类型、枚举类型)。
> * 根据`指针变量`所`指向空间`中`存储`的`值`的类型不同,可以将`指针类型`分为`基本数据类型指针`、`复合数据类型指针`、`函数指针`、`数组指针`等,例如:如果指针所指向的空间保存的是 int 类型,那么该指针就是 int 类型的指针。
## 1.2 整数类型
### 1.2.1 概述
* 整数类型简称整型用于存储整数值12、20、50 等。
* 根据所占`内存空间`大小的不同,可以将整数类型划分为:
* ① 短整型:
| 类型 | 存储空间(内存空间) | 取值范围 |
| ------------------------------------ | -------------------- | ----------------------------------- |
| unsigned short (无符号短整型) | 2 字节 | 0 ~ 65,535 (2^16 - 1) |
| [signed] short有符号短整型默认 | 2 字节 | -32,768 (- 2^15) ~ 32,767 (2^15 -1) |
* ② 整型:
| 类型 | 存储空间(内存空间) | 取值范围 |
| -------------------------------- | -------------------- | ------------------------------------------- |
| unsigned int无符号整型 | 4 字节(通常) | 0 ~ 4294967295 (0 ~2^32 -1) |
| [signed] int有符号整型默认 | 4 字节(通常) | -2147483648- 2^31 ~ 2147483647 (2^31-1) |
* ③ 长整型:
| 类型 | 存储空间(内存空间) | 取值范围 |
| ----------------------------------- | -------------------- | --------------- |
| unsigned long无符号长整型 | 4 字节(通常) | 0 ~2^32 -1 |
| [signed] long有符号长整型默认 | 4 字节(通常) | - 2^31 ~ 2^31-1 |
* ④ 长长整型:
| 类型 | 存储空间(内存空间) | 取值范围 |
| ---------------------------------------- | -------------------- | --------------- |
| unsigned long long无符号长整型 | 8 字节(通常) | 0 ~2^64 -1 |
| [signed] long long有符号长整型默认 | 8 字节(通常) | - 2^63 ~ 2^63-1 |
> [!NOTE]
>
> * ① C 语言默认没有规定各种数据类型所占存储单元的长度,但是通常需要遵守:`sizeof(short int) ≤ sizeof(int) ≤ sizeof(long int) ≤ sizeof(long long)` 具体的存储空间由编译系统自行决定其中sizeof 是测量类型或变量、常量长度的运算符。
> * ② short 至少 2 个字节long 至少 4 个字节。
> * ③ 之所以这么规定,是为了可以让 C 语言长久使用,因为目前主流的 CPU 都是 64 位,但是在 C语言刚刚出现的时候CPU 还是以 8 位和 16 位为主。如果当时就将整型定死为 8 位或 16 位,那么现在我们肯定不会再学习 C 语言了。
> * ④ 整型分为有符号 signed 和无符号 unsigned 两种,默认是 signed。
> * ⑤ 在实际开发中,`最常用的整数类型`就是 `int` 类型了,如果取值范围不够,就使用 long 或 long long 。
> * ⑥ C 语言中的`格式占位符`非常多,只需要大致了解即可;因为,我们在实际开发中,一般都会使用 C++ 或 Rust 以及其它的高级编程语言Java 等,早已经解决了需要通过`格式占位符`来输入和输出变量。
### 1.2.2 短整型(了解)
* 语法:
```c
unsigned short x = 10 ; // 无符号短整型
```
```c
short x = -10; // 有符号短整型
```
> [!NOTE]
>
> * ① 有符号表示的是正数、负数和 0 ,即有正负号。无符号表示的是 0 和正数,即正整数,没有符号。
> * ② 在 `printf` 中`无符号短整型unsigned short`的`格式占位符`是 `%hu` `有符号短整型signed short`的`格式占位符`是 `%hd`
> * ③ 可以通过 `sizeof` 运算符获取`无符号短整型unsigned short` 和 `有符号短整型signed short` 的`存储空间(所占内存空间)`。
> * ③ 可以通过 `#include <limits.h>` 来获取 `无符号短整型unsigned short` 和`有符号短整型signed short`的`取值范围`。
* 示例:定义和打印短整型变量
```c
#include <stdio.h>
int main() {
// 定义有符号 short 类型
signed short s1 = -100;
printf("s1 = %hd \n", s1); // s1 = -100
// 定义无符号 short 类型
unsigned short s2 = 100;
printf("s2 = %hu \n", s2); // s2 = 100
// 定义 short 类型,默认是有符号
short s3 = -200;
printf("s3 = %hd \n", s3); // s3 = -200
return 0;
}
```
* 示例:获取类型占用的内存大小(存储空间)
```c
#include <stdio.h>
int main() {
size_t s1 = sizeof(unsigned short);
printf("unsigned short 的存储空间是 %zu 字节 \n", s1); // 2
size_t s2 = sizeof(signed short);
printf("signed short 的存储空间是 %zu 字节 \n", s2); // 2
size_t s3 = sizeof(short);
printf("short 的存储空间是 %zu 字节 \n", s3); // 2
return 0;
}
```
* 示例:获取类型的取值范围
```c
#include <limits.h>
#include <stdio.h>
int main() {
printf("unsigned short 类型的范围是[0,%hu]\n", USHRT_MAX); // [0,65535]
printf("short 类型的范围是[%hd,%hd]\n", SHRT_MIN,SHRT_MAX); // [-32768,32767]
return 0;
}
```
### 1.2.3 整型
* 语法:
```c
unsigned int x = 10 ; // 无符号整型
```
```c
int x = -10; // 有符号整型
```
> [!NOTE]
>
> * ① 有符号表示的是正数、负数和 0 ,即有正负号。无符号表示的是 0 和正数,即正整数,没有符号。
> * ② 在 `printf` 中`无符号整型unsigned int`的`格式占位符`是 `%u` `有符号整型signed int`的`格式占位符`是 `%d`
> * ③ 可以通过 `sizeof` 运算符获取`无符号整型unsigned int` 和 `有符号整型signed int` 的`存储空间(所占内存空间)`。
> * ③ 可以通过 `#include <limits.h>` 来获取 `无符号整型unsigned int` 和`有符号整型signed int`的`取值范围`。
* 示例:定义和打印整型变量
```c
#include <stdio.h>
int main() {
// 定义有符号 int 类型
signed int i1 = -100;
printf("i1 = %d \n", i1); // i1 = -100
// 定义无符号 int 类型
unsigned int i2 = 100;
printf("i2 = %u \n", i2); // i2 = 100
// 定义 int 类型,默认是有符号
short i3 = -200;
printf("i3 = %d \n", i3); // i3 = -200
return 0;
}
```
* 示例:获取类型占用的内存大小(存储空间)
```c
#include <stdio.h>
int main() {
size_t i1 = sizeof(unsigned int);
printf("unsigned int 的存储空间是 %zu 字节 \n", i1); // 4
size_t i2 = sizeof(signed int);
printf("signed int 的存储空间是 %zu 字节 \n", i2); // 4
size_t i3 = sizeof(int);
printf("int 的存储空间是 %zu 字节 \n", i3); // 4
return 0;
}
```
* 示例:获取类型的取值范围
```c
#include <limits.h>
#include <stdio.h>
int main() {
printf("unsigned int 类型的范围是[0,%u]\n", UINT_MAX); // [0,4294967295]
printf("int 类型的范围是[%d,%d]\n", INT_MIN,INT_MAX); // [-2147483648,2147483647]
return 0;
}
```
### 1.2.4 长整型(了解)
* 语法:
```c
unsigned long x = 10 ; // 无符号长整型
```
```c
long x = -10; // 有符号长整型
```
> [!NOTE]
>
> * ① 有符号表示的是正数、负数和 0 ,即有正负号。无符号表示的是 0 和正数,即正整数,没有符号。
> * ② 在 `printf` 中`无符号长整型unsigned long`的`格式占位符`是 `%lu` `有符号长整型signed long`的`格式占位符`是 `%ld`
> * ③ 可以通过 `sizeof` 运算符获取`无符号长整型unsigned long` 和 `有符号长整型signed long` 的`存储空间(所占内存空间)`。
> * ③ 可以通过 `#include <limits.h>` 来获取 `无符号长整型unsigned long` 和`有符号长整型signed long`的`取值范围`。
* 示例:定义和打印长整型变量
```c
#include <stdio.h>
int main() {
// 定义有符号 long 类型
signed long l1 = -100;
printf("l1 = %ld \n", l1); // l1 = -100
// 定义无符号 long 类型
unsigned long l2 = 100;
printf("l2 = %lu \n", l2); // l2 = 100
// 定义 long 类型,默认是有符号
long l3 = -200;
printf("l3 = %ld \n", l3); // l3 = -200
return 0;
}
```
* 示例:获取类型占用的内存大小(存储空间)
```c
#include <stdio.h>
int main() {
size_t l1 = sizeof(unsigned long);
printf("unsigned long 的存储空间是 %zu 字节 \n", l1); // 4
size_t l2 = sizeof(signed long);
printf("signed long 的存储空间是 %zu 字节 \n", l2); // 4
size_t l3 = sizeof(long);
printf("long 的存储空间是 %zu 字节 \n", l3); // 4
return 0;
}
```
* 示例:获取类型的取值范围
```c
#include <limits.h>
#include <stdio.h>
int main() {
printf("unsigned long 类型的范围是[0,%lu]\n", ULONG_MAX); // [0,4294967295]
printf("long 类型的范围是[%ld,%ld]\n", LONG_MIN,LONG_MAX); // [-2147483648,2147483647]
return 0;
}
```
### 1.2.5 长长整型(了解)
* 语法:
```c
unsigned long long x = 10 ; // 无符号长长整型
```
```c
long long x = -10; // 有符号长长整型
```
> [!NOTE]
>
> * ① 有符号表示的是正数、负数和 0 ,即有正负号。无符号表示的是 0 和正数,即正整数,没有符号。
> * ② 在 `printf` 中`无符号长长整型unsigned long long`的`格式占位符`是 `%llu` `有符号长长整型signed long long`的`格式占位符`是 `%lld`
> * ③ 可以通过 `sizeof` 运算符获取`无符号长长整型unsigned long long` 和 `有符号长长整型signed long long` 的`存储空间(所占内存空间)`。
> * ③ 可以通过 `#include <limits.h>` 来获取 `无符号长长整型unsigned long long` 和`有符号长长整型signed long long`的`取值范围`。
* 示例:定义和打印长长整型变量
```c
#include <stdio.h>
int main() {
// 定义有符号 long long 类型
signed long long ll1 = -100;
printf("ll1 = %lld \n", ll1); // ll1 = -100
// 定义无符号 long long 类型
unsigned long long ll2 = 100;
printf("ll2 = %llu \n", ll2); // ll2 = 100
// 定义 long long 类型,默认是有符号
long long ll3 = -200;
printf("ll3 = %lld \n", ll3); // ll3 = -200
return 0;
}
```
* 示例:获取类型占用的内存大小(存储空间)
```c
#include <stdio.h>
int main() {
size_t ll1 = sizeof(unsigned long long);
printf("unsigned long long 的存储空间是 %zu 字节 \n", ll1); // 8
size_t ll2 = sizeof(signed long long);
printf("signed long long 的存储空间是 %zu 字节 \n", ll2); // 8
size_t ll3 = sizeof(long long);
printf("long long 的存储空间是 %zu 字节 \n", ll3); // 8
return 0;
}
```
* 示例:获取类型的取值范围
```c
#include <limits.h>
#include <stdio.h>
int main() {
printf("unsigned long long 类型的范围是[0,%llu]\n", ULLONG_MAX); // [0,18446744073709551615]
printf("long long 类型的范围是[%lld,%lld]\n", LLONG_MIN,LLONG_MAX); // [-9223372036854775808,9223372036854775807]
return 0;
}
```
### 1.2.6 字面量后缀
* `字面量`是`源代码`中一个`固定值`的`表示方法`,用于直接表示数据,即:
```c
int num1 = 100; // 100 就是字面量
```
```c
long num2 = 100L; // 100L 就是字面量
```
```c
long long num3 = 100LL; // 100LL 就是字面量
```
> [!NOTE]
>
> * ① 默认情况下的,整数字面量的类型是 int 类型。
> * ② 如果需要表示 long 类型的字面量,需要添加后缀 l 或 L ,建议 L。
> * ③ 如果需要表示 long long类型的字面量需要添加后缀 ll 或 LL建议 LL 。
> * ④ 如果需要表示无符号整数类型的字面量,需要添加 u 或 U建议 U 。
* 示例:
```c
#include <stdio.h>
int main() {
int num = 100;
printf("num = %d\n", num); // num = 100
long num2 = 100L;
printf("num2 = %ld\n", num2); // num2 = 100
long long num3 = 100LL;
printf("num3 = %lld\n", num3); // num3 = 100
unsigned int num4 = 100U;
printf("num4 = %u\n", num4); // num4 = 100
unsigned long num5 = 100LU;
printf("num5 = %lu\n", num5); // num5 = 100
unsigned long long num6 = 100ULL;
printf("num6 = %llu\n", num6); // num6 = 100
return 0;
}
```
### 1.2.7 精确宽度类型
* 在前文,我们了解到 C 语言的整数类型short 、int、long、long long在不同计算机上占用的字节宽度可能不一样。但是有的时候我们希望整数类型的存储空间字节宽度是精确的在任意平台计算机上都能一致以提高程序的可移植性。
> [!NOTE]
>
> * Java 语言中的数据类型的存储空间(字节宽度)是一致的,这也是 Java 语言能够跨平台的原因之一(最主要的原因还是 JVM
> * 在嵌入式开发中,使用精确宽度类型可以确保代码在各个平台上的一致性。
* 在 C 语言的标准头文件 `<stdint.h>` 中定义了一些新的类型别名,如下所示:
| 类型名称 | 含义 |
| -------- | --------------- |
| int8_t | 8 位有符号整数 |
| int16_t | 16 位有符号整数 |
| int32_t | 32 位有符号整数 |
| int64_t | 64 位有符号整数 |
| uint8_t | 8 位无符号整数 |
| uint16_t | 16 位无符号整数 |
| uint32_t | 32 位无符号整数 |
| uint64_t | 64 位无符号整数 |
> [!NOTE]
>
> 上面的这些类型都是类型别名,编译器会指定它们指向的底层类型,如:在某个系统中,如果 int 类型是 32 位,那么 int32_t 就会指向 int ;如果 long 类型是 32 位,那么 int32_t 就会指向 long。
* 示例:
```c
#include <stdio.h>
#include <stdint.h>
int main() {
// 变量 x32 声明为 int32_t 类型,可以保证是 32 位(4个字节)的宽度。
int32_t x32 = 45933945;
printf("x32 = %d \n", x32); // x32 = 45933945
return 0;
}
```
### 1.2.8 sizeof 运算符
* 语法:
```c
sizeof(表达式)
```
> [!NOTE]
>
> * ① 表达式可以是任何类型的数据类型、变量或常量。
> * ② 返回某种数据类型或某个值占用的字节数量,并且 `sizeof(...)` 的`返回值类型`是 `size_t`
> * ③ 在 `printf` 中使用占位符 `%zu` 来处理 `size_t` 类型的值。
* 示例:参数是数据类型
```c
#include <stdio.h>
#include <stddef.h>
int main() {
size_t s = sizeof(int);
printf("%zu \n", s); // 4
return 0;
}
```
* 示例:参数是变量
```c
#include <stdio.h>
#include <stddef.h>
int main() {
int num = 10;
size_t s = sizeof(num);
printf("%zu \n", s); // 4
return 0;
}
```
* 示例:参数是常量
```c
#include <stdio.h>
#include <stddef.h>
int main() {
size_t s = sizeof(10);
printf("%zu \n", s); // 4
return 0;
}
```
### 1.2.9 数值溢出
* 所谓的数值溢出指的是:当超过一个数据类型能够存放的最大范围的时候,数值就会溢出。
* 如果达到了最大值,再进行加法计算,数据就会超过该类型能够表示的最大值,叫做上溢出。
* 如果这个数目前是最小值,再进行减法计算, 数据就会超过该类型的最小值, 叫做下溢出。
* 在 C 语言中,`整数`的`数据类型`分为`无符号`和`有符号`的,其在底层表示和存储是不一样的,即:
* `无符号整数不使用最高位作为符号位`,所有的位都用于表示数值,如:对于一个 4 位无符号整数,二进制表示的范围是从 0000 到 1111 ,那么十进制表示的范围是从 0 到 15。
* `有符号整数使用最高位作为符号位`,这意味着它们可以表示正数和负数,通常使用补码来表示有符号整数。在补码表示法中:最高位为 0 表示正数、最高位为 1 表示负数对于一个4位有符号整数二进制表示的范围是从 00000 到 0111 71000 -8到 1111-1
> [!NOTE]
>
> * 在 C 语言中,无符号整数,最高位不是符号位,它是数值的一部分。
> * 在 C 语言中,有符号整数,最高位是符号位,用于表示正负数。
* 对于无符号的数值溢出:
* 当数据到达最大值的时候,再加 1 就会回到无符号数的最小值。
* 当数据达到最小值的时候,再减 1 就会回到无符号数的最大值。
* 那么,无符号的上溢出,原理就是这样的:
![](./assets/3.png)
* 那么,无符号的下溢出,原理就是这样的(需要先借位,然后再减):
![](./assets/4.png)
* 对于有符号的数值溢出:
* 当数据到达最大值的时候,再加 1 就会回到有符号数的最小值。
* 当数据达到最小值的时候,再减 1 就会回到有符号数的最大值。
* 那么,有符号的上溢出,原理就是这样的:
![](./assets/5.png)
* 那么,有符号的下溢出,原理就是这样的:
![](./assets/6.png)
> [!NOTE]
>
> 在实际开发中,选择合适的数据类型,以避免数值溢出问题!!!
* 示例:无符号的上溢出和下溢出
```c
#include <limits.h>
#include <stdio.h>
int main() {
unsigned short s1 = USHRT_MAX + 1;
printf("无符号的上溢出 = %hu \n", s1); // 0
unsigned short s2 = 0 - 1;
printf("无符号的下溢出 = %hu \n", s2); // 65535
return 0;
}
```
* 示例:有符号的上溢出和下溢出
```c
#include <limits.h>
#include <stdio.h>
int main() {
short s1 = SHRT_MAX + 1;
printf("有符号的上溢出 = %hd \n", s1); // -32768
short s2 = SHRT_MIN - 1;
printf("有符号的下溢出 = %hd \n", s2); // 32767
return 0;
}
```
## 1.3 浮点类型
### 1.3.1 概述
* 在生活中,我们除了使用`整数`18、25 之外,还会使用到`小数`3.1415926、6.18 等,`小数`在计算机中也被称为`浮点数`(和底层存储有关)。
* `整数`在计算机底层的存储被称为`定点存储`,如下所示:
![](./assets/7.png)
* `小数`在计算机底层的存储被称为`浮点存储`,如下所示:
![](./assets/8.png)
> [!NOTE]
>
> * ① 计算机底层就是采取类似科学计数法的形式来存储小数的而科学技术法的表现就是这样的3.12 * 10^-2 其中10 是基数,-2 是指数,而 3.12 是尾数。
> * ② 因为尾数区的内存空间的宽度不同,导致了小数的精度也不相同,所以小数在计算机中也称为浮点数。
* 在 C 语言中,变量的浮点类型,如下所示:
| 类型 | 存储大小 | 值的范围 | 有效小数位数 |
| ----------------------- | -------- | --------------------- | ------------ |
| float单精度 | 4 字节 | 1.2E-38 ~ 3.4E+38 | 6 ~ 9 |
| double双精度 | 8 字节 | 2.3E-308 ~ 1.7E+308 | 15 ~ 18 |
| long double长双精度 | 16 字节 | 3.4E-4932 ~ 1.2E+4932 | 18 或更多 |
> [!NOTE]
>
> * ① 各类型的存储大小和精度受到操作系统、编译器、硬件平台的影响。
> * ② 浮点型数据有两种表现形式:
> * 十进制数形式3.12、512.0f、0.512.512,可以省略 0
> * 科学计数法形式5.12e2e 表示基数 10、5.12E-2E 表示基数 10
> * ③ 在实际开发中,对于浮点类型,建议使用 double 类型;如果范围不够,就使用 long double 类型。
### 1.3.2 格式占位符
* 对于 float 类型的格式占位符,是 `%f` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2f` 表示保留 `2` 位小数。
* 对于 double 类型的格式占位符,是 `%lf` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2lf` 表示保留 `2` 位小数。
* 对于 long double 类型的格式占位符,是 `%Lf` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2Lf` 表示保留 `2` 位小数。
* 如果想输出`科学计数法`形式的浮点数,则使用 `%e`
* 示例:
```c
#include <stdio.h>
int main() {
float f1 = 10.0;
printf("f1 = %f \n", f1); // f1 = 10.000000
printf("f1 = %.2f \n", f1); // f1 = 10.00
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
double d1 = 13.14159265354;
printf("d1 = %lf \n", d1); // d1 = 13.141593
printf("d1 = %.2lf \n", d1); // d1 = 13.14
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
long double d1 = 13.14159265354;
printf("d1 = %LF \n", d1); // d1 = 13.141593
printf("d1 = %.2LF \n", d1); // d1 = 13.14
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
float f1 = 3.1415926;
double d2 = 3.14e2;
printf("f1 = %.2f \n", f1); // f1 = 3.14
printf("f1 = %.2e \n", f1); // f1 = 3.14e+00
printf("d2 = %.2lf \n", d2); // d2 = 314.00
printf("d2 = %.2e \n", d2); // d2 = 3.14e+02
return 0;
}
```
### 1.3.3 字面量后缀
* 浮点数字面量默认是 double 类型。
* 如果需要表示 float 类型的字面量,需要后面添加后缀 f 或 F。
* 如果需要表示 long double 类型的字面量,需要后面添加后缀 l 或 L。
* 示例:
```c
#include <stdio.h>
int main() {
float f1 = 3.1415926f;
double d2 = 3.1415926;
long double d3 = 3.1415926L;
printf("f1 = %.2f \n", f1); // f1 = 3.14
printf("d2 = %.3lf \n", d2); // d2 = 3.142
printf("d3 = %.4Lf \n", d3); // d3 = 3.1416
return 0;
}
```
### 1.3.4 类型占用的内存大小(存储空间)
* 可以通过 sizeof 运算符来获取 float、double 以及 long double 类型占用的内存大小(存储空间)。
* 示例:
```c
#include <stdio.h>
int main() {
printf("float 的存储空间是 %zu 字节 \n", sizeof(float)); // 4
printf("double 的存储空间是 %zu 字节 \n", sizeof(double)); // 8
printf("long double 的存储空间是 %zu 字节 \n", sizeof(long double)); // 16
return 0;
}
```
### 1.3.5 类型的取值范围
* 可以通过 `#include <float.h>` 来获取类型的取值范围。
* 示例:
```c
#include <float.h>
#include <stdio.h>
int main() {
printf("float 的取值范围是:[%.38f, %f] \n", FLT_MIN, FLT_MAX);
printf("double 的取值范围是:[%lf, %lf] \n", DBL_MIN, DBL_MAX);
printf("double 的取值范围是:[%Lf, %Lf] \n", LDBL_MIN, LDBL_MAX);
return 0;
}
```
## 1.4 字符类型
### 1.4.1 概述
* 在生活中,我们会经常说:今天天气真 `好`,我的性别是 `女`,我今年 `10` 岁,像这类数据,在 C 语言中就可以用字符char来表示。
* 在 C 语言中,变量的`字符类型`可以表示`单`个字符,如:`'1'`、`'A'`、`'&'`。
> [!NOTE]
>
> * C 语言的出现在 1972 年,由美国人丹尼斯·里奇设计出来;那个时候,只需要 1 个字节的内存空间就可以完美的表示拉丁体系英文文字a-z、A-Z、0-9 以及一些特殊符号所以C 语言中不支持多个字节的字符,如:中文、日文等。
> * C 语言中没有字符串类型是使用字符数组char 数组)来模拟字符串的,并且字符数组也不是字符串,而是构造类型。
> * 在 C 语言中如果想要输出中文、日文等多字节字符就需要使用字符数组char 数组)。
> * 在 C++、Java 等高级编程语言中,已经提供了 String (字符串)类型,原生支持 Unicode可以方便地处理多语言和特殊字符。
* 在 C 语言中,可以使用`转义字符 \`来表示特殊含义的字符。
| **转义字符** | **说明** |
| ------------ | -------- |
| `\b` | 退格 |
| `\n` | 换行符 |
| `\r` | 回车符 |
| `\t` | 制表符 |
| `\"` | 双引号 |
| `\'` | 单引号 |
| `\\` | 反斜杠 |
| ... | |
### 1.4.2 格式占位符
* 在 C 语言中,使用 `%c` 来表示 char 类型。
* 示例:
```c
#include <stdio.h>
int main() {
char c = '&';
printf("c = %c \n", c); // c = &
char c2 = 'a';
printf("c2 = %c \n", c2); // c2 = a
char c3 = 'A';
printf("c3 = %c \n", c3); // c3 = A
return 0;
}
```
### 1.4.3 类型占用的内存大小(存储空间)
* 可以通过 sizeof 运算符来获取 char 类型占用的内存大小(存储空间)。
* 示例:
```c
#include <stdio.h>
int main() {
printf("char 的存储空间是 %d 字节\n", sizeof(char)); // 1
printf("unsigned char 的存储空间是 %d 字节\n", sizeof(unsigned char)); // 1
return 0;
}
```
### 1.4.4 类型的取值范围
* 可以通过 `#include <limits.h>` 来获取类型的取值范围。
* 示例:
```c
#include <limits.h>
#include <stdio.h>
int main() {
printf("char 范围是[%d,%d] \n", CHAR_MIN,CHAR_MAX); // [-128,127]
printf("unsigned char 范围是[0,%d]\n", UCHAR_MAX); // [0,255]
return 0;
}
```
### 1.4.5 字符类型的本质
* 在 C 语言中char 本质上就是一个整数,是 ASCII 码中对应的数字,占用的内存大小是 1 个字节(存储空间),所以 char 类型也可以进行数学运算。
![](./assets/9.png)
* char 类型同样分为 signed char无符号和 unsigned char有符号其中 signed char 取值范围 -128 ~ 127unsigned char 取值范围 0 ~ 255默认是否带符号取决于当前运行环境。
* `字符类型的数据`在计算机中`存储`和`读取`的过程,如下所示:
![](./assets/10.png)
* 示例:
```c
#include <limits.h>
#include <stdio.h>
int main() {
// char 类型字面量需要使用单引号包裹
char a1 = 'A';
char a2 = '9';
char a3 = '\t';
printf("c1=%c, c3=%c, c2=%c \n", a1, a3, a2);
// char 类型本质上整数可以进行运算
char b1 = 'b';
char b2 = 101;
printf("%c->%d \n", b1, b1);
printf("%c->%d \n", b2, b2);
printf("%c+%c=%d \n", b1, b2, b1 + b2);
// char 类型取值范围
unsigned char c1 = 200; // 无符号 char 取值范围 0 ~255
signed char c2 = 200; // 有符号 char 取值范围 -128~127c2会超出范围
char c3 = 200; // 当前系统char 默认是 signed char
printf("c1=%d, c2=%d, c3=%d", c1, c2, c3);
return 0;
}
```
## 1.5 布尔类型
### 1.5.1 概述
* 布尔值用于表示 true、false两种状态通常用于逻辑运算和条件判断。
### 1.5.2 早期的布尔类型
* 在 C 语言标准C89并没有为布尔值单独设置一个数据类型所以在判断真、假的时候使用 `0` 表示 `false`(假),`非 0` 表示 `true`(真)。
* 示例:
```c
#include <stdio.h>
int main() {
// 使用整型来表示真和假两种状态
int handsome = 0;
printf("帅不帅[0 丑1 帅] ");
scanf("%d", &handsome);
if (handsome) {
printf("你真的很帅!!!");
} else {
printf("你真的很丑!!!");
}
return 0;
}
```
### 1.5.3 宏定义的布尔类型
* 判断真假的时候,以 `0``false`(假)、`1` 为 `true`(真),并不直观;所以,我们可以借助 C 语言的宏定义。
* 示例:
```c
#include <stdio.h>
// 宏定义
#define BOOL int
#define TRUE 1
#define FALSE 0
int main() {
BOOL handsome = 0;
printf("帅不帅[FALSE 丑TRUE 帅] ");
scanf("%d", &handsome);
if (handsome) {
printf("你真的很帅!!!");
} else {
printf("你真的很丑!!!");
}
return 0;
}
```
### 1.5.4 C99 标准中的布尔类型
* 在 C99 中提供了 `_Bool` 关键字,用于表示布尔类型;其实,`_Bool`类型的值是整数类型的别名,和一般整型不同的是,`_Bool`类型的值只能赋值为 `0``1` 0 表示假、1 表示真),其它`非 0` 的值都会被存储为 `1`
* 示例:
```c
#include <stdio.h>
int main() {
_Bool handsome = 0;
printf("帅不帅[0 丑1 帅] ");
scanf("%d", &handsome);
if (handsome) {
printf("你真的很帅!!!");
} else {
printf("你真的很丑!!!");
}
return 0;
}
```
### 1.5.5 C99 标准头文件中的布尔类型(推荐)
* 在 C99 中提供了一个头文件 `<stdbool.h>`,定义了 `bool` 代表 `_Bool``false` 代表 `0` `true` 代表 `1`
> [!NOTE]
>
> 在 C++、Java 等高级编程语言中是有 boolean 类型的关键字的。
* 示例:
```c
#include <stdio.h>
int main() {
bool handsome = false;
printf("帅不帅[false 丑true 帅] ");
scanf("%d", &handsome);
if (handsome) {
printf("你真的很帅!!!");
} else {
printf("你真的很丑!!!");
}
return 0;
}
```
## 1.6 数据类型转换
### 1.6.1 概述
* 在 C 语言编程中,经常需要对不同类型的数据进行运算,运算前需要先转换为同一类型,再运算。为了解决数据类型不一致的问题,需要对数据的类型进行转换。
### 1.6.2 自动类型转换(隐式转换)
#### 1.6.2.1 运算过程中的自动类型转换
* 不同类型的数据进行混合运算的时候,会发生数据类型转换,`窄类型会自动转换为宽类型`,这样就不会造成精度损失。
![](./assets/11.png)
* 转换规则:
* ① 不同类型的整数进行运算的时候,窄类型整数会自动转换为宽类型整数。
* ② 不同类型的浮点数进行运算的时候,精度小的类型会自动转换为精度大的类型。
* ③ 整数和浮点数进行运算的时候,整数会自动转换为浮点数。
* 转换方向:
![](./assets/12.png)
> [!NOTE]
>
> 最好避免无符号整数与有符号整数的混合运算,因为这时 C 语言会自动将 signed int 转为 unsigned int ,可能不会得到预期的结果。
* 示例:
```c
#include <stdio.h>
/**
* 不同的整数类型混合运算时,宽度较小的类型会提升为宽度较大的类型,比如 short 转为 int int 转为 long 等。
*/
int main() {
short s1 = 10;
int i = 20;
// s1 是 short 类型i 是 int 类型,当 s1 和 i 运算的时候,会自动转为 int 类型后,然后再计算。
int result = s1 + i;
printf("result = %d \n", result);
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
int n2 = -100;
unsigned int n3 = 20;
// n2 是有符号n3 是无符号,当 n2 和 n3 运算的时候,会自动转为无符号类型后,然后再计算。
int result = n2 + n3;
printf("result = %d \n", result);
return 0;
}
```
* 示例:
```c
#include <stdio.h>
/**
* 不同的浮点数类型混合运算时,宽度较小的类型转为宽度较大的类型,比如 float 转为 double double 转为 long double 。
*/
int main() {
float f1 = 1.25f;
double d2 = 4.58667435;
// f1 是 float 类型d2 是 double 类型,当 f1 和 d2 运算的时候,会自动转为 double 类型后,然后再计算。
double result = f1 + d2;
printf("result = %.8lf \n", result);
return 0;
}
```
* 示例:
```c
#include <stdio.h>
/**
* 整型与浮点型运算,整型转为浮点型
*/
int main() {
int n4 = 10;
double d3 = 1.67;
// n4 是 int 类型d3 是 double 类型,当 n4 和 d3 运算的时候,会自动转为 double 类型后,然后再计算。
double result = n4 + d3;
printf("%.2lf", result);
return 0;
}
```
#### 1.6.2.2 赋值时的自动类型转换
* 在赋值运算中,赋值号两边量的数据类型不同时,等号右边的类型将转换为左边的类型。
* 如果窄类型赋值给宽类型,不会造成精度损失;如果宽类型赋值给窄类型,会造成精度损失。
![](./assets/14.png)
> [!NOTE]
>
> C 语言在检查类型匹配方面不太严格,最好不要养成这样的习惯。
* 示例:
```c
#include <stdio.h>
int main() {
// 赋值:窄类型赋值给宽类型
int a1 = 10;
double a2 = a1;
printf("a2: %.2f\n", a2); // a2: 10.00
// 转换:将宽类型转换为窄类型
double b1 = 10.5;
int b2 = b1;
printf("b2: %d\n", b2); // b2: 10
return 0;
}
```
### 1.6.3 强制类型转换
* 隐式类型转换中的宽类型赋值给窄类型,编译器是会产生警告的,提示程序存在潜在的隐患,如果非常明确地希望转换数据类型,就需要用到强制(或显式)类型转换。
* 语法:
```c
数据类型 变量名 = (类型名)变量、常量或表达式;
```
> [!NOTE]
>
> 强制类型转换可能会导致精度损失!!!
* 示例:
```c
#include <stdio.h>
int main(){
double d1 = 1.934;
double d2 = 4.2;
int num1 = (int)d1 + (int)d2; // d1 转为 1d2 转为 4结果是 5
int num2 = (int)(d1 + d2); // d1+d2 = 6.1346.134 转为 6
int num3 = (int)(3.5 * 10 + 6 * 1.5); // 35.0 + 9.0 = 44.0 -> int = 44
printf("num1=%d \n", num1);
printf("num2=%d \n", num2);
printf("num3=%d \n", num3);
return 0;
}
```
# 第二章:运算符(⭐)
## 2.1 概述
* 运算符是一种特殊的符号,用于数据的运算、赋值和比较等。
* `表达式`指的是一组运算数、运算符的组合,表达式`一定具有值`,一个变量或一个常量可以是表达式,变量、常量和运算符也可以组成表达式,如:
![](./assets/15.png)
* `操作数`指的是`参与运算`的`值`或者`对象`,如:
![](./assets/16.png)
* 根据`操作数`的`个数`,可以将运算符分为:
* 一元运算符(一目运算符)。
* 二元运算符(二目运算符)。
* 三元运算符(三目运算符)。
* 根据`功能`,可以将运算符分为:
* 算术运算符。
* 关系运算符(比较运算符)。
* 逻辑运算符。
* 赋值运算符。
* 逻辑运算符。
* 位运算符。
* 三元运算符。
> [!NOTE]
>
> 掌握一个运算符,需要关注以下几个方面:
>
> * ① 运算符的含义。
> * ② 运算符操作数的个数。
> * ③ 运算符所组成的表达式。
> * ④ 运算符有无副作用,即:运算后是否会修改操作数的值。
## 2.2 算术运算符
* 算术运算符是对数值类型的变量进行运算的,如下所示:
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | ------------ | ---------- | ------------------------ | ------ |
| `+` | 正号 | 1 | 操作数本身 | ❎ |
| `-` | 负号 | 1 | 操作数符号取反 | ❎ |
| `+` | 加号 | 2 | 两个操作数之和 | ❎ |
| `-` | 减号 | 2 | 两个操作数之差 | ❎ |
| `*` | 乘号 | 2 | 两个操作数之积 | ❎ |
| `/` | 除号 | 2 | 两个操作数之商 | ❎ |
| `%` | 取模(取余) | 2 | 两个操作数相除的余数 | ❎ |
| `++` | 自增 | 1 | 操作数自增前或自增后的值 | ✅ |
| `--` | 自减 | 1 | 操作数自减前或自减后的值 | ✅ |
> [!NOTE]
>
> 自增和自减:
>
> * ① 自增、自减运算符可以写在操作数的前面也可以写在操作数后面,不论前面还是后面,对操作数的副作用是一致的。
> * ② 自增、自减运算符在前在后,对于表达式的值是不同的。 如果运算符在前,表达式的值是操作数自增、自减之后的值;如果运算符在后,表达式的值是操作数自增、自减之前的值。
> * ③ `变量前++`:变量先自增 1 ,然后再运算;`变量后++`:变量先运算,然后再自增 1 。
> * ④ `变量前--`:变量先自减 1 ,然后再运算;`变量后--`:变量先运算,然后再自减 1 。
* 示例:正号和负号
```c
#include <stdio.h>
int main() {
int x = 12;
int x1 = -x, x2 = +x;
int y = -67;
int y1 = -y, y2 = +y;
printf("x1=%d, x2=%d \n", x1, x2); // x1=-12, x2=12
printf("y1=%d, y2=%d \n", y1, y2); // y1=67, y2=-67
return 0;
}
```
* 示例:加、减、乘、除(整数之间做除法时,结果只保留整数部分而舍弃小数部分)、取模
```c
#include <stdio.h>
int main() {
int a = 5;
int b = 2;
printf("%d + %d = %d\n", a, b, a + b); // 5 + 2 = 7
printf("%d - %d = %d\n", a, b, a - b); // 5 - 2 = 3
printf("%d × %d = %d\n", a, b, a * b); // 5 × 2 = 10
printf("%d / %d = %d\n", a, b, a / b); // 5 / 2 = 2
printf("%d %% %d = %d\n", a, b, a % b); // 5 % 2 = 1
return 0;
}
```
* 示例:取模(运算结果的符号与被模数也就是第一个操作数相同。)
```c
#include <stdio.h>
int main() {
int res1 = 10 % 3;
printf("10 %% 3 = %d\n", res1); // 10 % 3 = 1
int res2 = -10 % 3;
printf("-10 %% 3 = %d\n", res2); // -10 % 3 = -1
int res3 = 10 % -3;
printf("10 %% -3 = %d\n", res3); // 10 % -3 = 1
int res4 = -10 % -3;
printf("-10 %% -3 = %d\n", res4); // -10 % -3 = -1
return 0;
}
```
* 示例:自增和自减
```c
#include <stdio.h>
int main() {
int i1 = 10, i2 = 20;
int i = i1++;
printf("i = %d\n", i); // i = 10
printf("i1 = %d\n", i1); // i1 = 11
i = ++i1;
printf("i = %d\n", i); // i = 12
printf("i1 = %d\n", i1); // i1 = 12
i = i2--;
printf("i = %d\n", i); // i = 20
printf("i2 = %d\n", i2); // i2 = 19
i = --i2;
printf("i = %d\n", i); // i = 18
printf("i2 = %d\n", i2); // i2 = 18
return 0;
```
* 示例:
```c
#include <stdio.h>
/*
随意给出一个整数,打印显示它的个位数,十位数,百位数的值。
格式如下:
数字xxx的情况如下
个位数:
十位数:
百位数:
例如:
数字153的情况如下
个位数3
十位数5
百位数1
*/
int main() {
int num = 153;
int bai = num / 100;
int shi = num % 100 / 10;
int ge = num % 10;
printf("百位为:%d \n", bai);
printf("十位为:%d \n", shi);
printf("个位为:%d \n", ge);
return 0;
}
```
## 2.3 关系运算符(比较运算符)
* 常见的关系运算符,如下所示:
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | -------- | ---------- | ---------------- | ------ |
| `==` | 相等 | 2 | 0 或 1 | ❎ |
| `!=` | 不相等 | 2 | 0 或 1 | ❎ |
| `<` | 小于 | 2 | 0 或 1 | ❎ |
| `>` | 大于 | 2 | 0 或 1 | ❎ |
| `<=` | 小于等于 | 2 | 0 或 1 | ❎ |
| `>=` | 大于等于 | 2 | 0 或 1 | ❎ |
> [!NOTE]
>
> * ① C 语言中,没有严格意义上的布尔类型,所以可以 0 或 1表示布尔类型的值。
> * ② 不要将 `==` 写成 `=``==` 是比较运算符,而 `=` 是赋值运算符。
> * ③ `>=``<=`含义是只需要满足 `大于或等于`、`小于或等于`其中一个条件,结果就返回真。
* 示例:
```c
#include <stdio.h>
int main() {
int a = 8;
int b = 7;
printf("a > b 的结果是:%d \n", a > b); // a > b 的结果是1
printf("a >= b 的结果是:%d \n", a >= b); // a >= b 的结果是1
printf("a < b 的结果是%d \n", a < b); // a < b 的结果是0
printf("a <= b 的结果是:%d \n", a <= b); // a <= b 的结果是0
printf("a == b 的结果是:%d \n", a == b); // a == b 的结果是0
printf("a != b 的结果是:%d \n", a != b); // a != b 的结果是1
return 0;
}
```
## 2.4 逻辑运算符
* 常见的逻辑运算符,如下所示:
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | ------ | ---------- | ---------------- | ------ |
| `&&` | 逻辑与 | 2 | 0 或 1 | ❎ |
| `\|\|` | 逻辑或 | 2 | 0 或 1 | ❎ |
| `!` | 逻辑非 | 2 | 0 或 1 | ❎ |
* 逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,如下所示:
| a | b | a && b | a \|\| b | !a |
| ------- | ------- | ------- | -------- | ------- |
| 1 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 0 | 0 | 0 | 0 | 1 |
> [!NOTE]
>
> * ① 对于逻辑运算符来说,任何非零值都表示真,零值表示假,如:`5 || 0` 返回 `1` `5 && 0` 返回 `0`
> * ② 短路现象:
> * 对于 `a && b` 操作来说,当 a 为假(或 0 )时,因为 `a && b` 结果必定为 0所以不再执行表达式 b。
> * 对于 `a || b` 操作来说,当 a 为真(或非 0 )时,因为 `a || b` 结果必定为 1所以不再执行表达式 b。
* 示例:
```c
#include <stdio.h>
int main() {
int a = 0;
int b = 0;
printf("请输入整数a的值");
scanf("%d", &a);
printf("请输入整数b的值");
scanf("%d", &b);
if (a > b) {
printf("%d > %d", a, b);
} else if (a < b) {
printf("%d < %d", a, b);
} else {
printf("%d = %d", a, b);
}
return 0;
}
```
* 示例:
```c
#include <stdio.h>
// 短路现象
int main() {
int i = 0;
int j = 10;
if (i && j++ > 0) {
printf("床前明月光\n"); // 这行代码不会执行
} else {
printf("我叫郭德纲\n");
}
printf("%d \n", j); //10
return 0;
}
```
* 示例:
```c
#include <stdio.h>
// 短路现象
int main() {
int i = 1;
int j = 10;
if (i || j++ > 0) {
printf("床前明月光 \n");
} else {
printf("我叫郭德纲 \n"); // 这行代码不会被执行
}
printf("%d\n", j); //10
return 0;
}
```
## 2.5 赋值运算符
* 常见的赋值运算符,如下所示:
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | ------------ | ---------- | ---------------- | ------ |
| `==` | 赋值 | 2 | 左边操作数的值 | ✅ |
| `+=` | 相加赋值 | 2 | 左边操作数的值 | ✅ |
| `-=` | 相减赋值 | 2 | 左边操作数的值 | ✅ |
| `*=` | 相乘赋值 | 2 | 左边操作数的值 | ✅ |
| `/=` | 相除赋值 | 2 | 左边操作数的值 | ✅ |
| `%=` | 取余赋值 | 2 | 左边操作数的值 | ✅ |
| `<<=` | 左移赋值 | 2 | 左边操作数的值 | ✅ |
| `>>=` | 右移赋值 | 2 | 左边操作数的值 | ✅ |
| `&=` | 按位与赋值 | 2 | 左边操作数的值 | ✅ |
| `^=` | 按位异或赋值 | 2 | 左边操作数的值 | ✅ |
| `\|=` | 按位或赋值 | 2 | 左边操作数的值 | ✅ |
> [!NOTE]
>
> * ① 赋值运算符的第一个操作数(左值)必须是变量的形式,第二个操作数可以是任何形式的表达式。
> * ② 赋值运算符的副作用针对第一个操作数。
* 示例:
```c
#include <stdio.h>
int main() {
int a = 3;
a += 3; // a = a + 3
printf("a = %d\n", a); // a = 6
int b = 3;
b -= 3; // b = b - 3
printf("b = %d\n", b); // b = 0
int c = 3;
c *= 3; // c = c * 3
printf("c = %d\n", c); // c = 9
int d = 3;
d /= 3; // d = d / 3
printf("d = %d\n", d); // d = 1
int e = 3;
e %= 3; // e = e % 3
printf("e = %d\n", e); // e = 0
return 0;
}
```
## 2.6 位运算符(了解)
### 2.6.1 概述
* C 语言提供了一些位运算符能够让我们操作二进制位bit
* 常见的位运算符,如下所示。
| 运算符 | 描述 | 操作数个数 | 运算规则 | 副作用 |
| ------ | ---------- | ---------- | ------------------------------------------------------------ | ------ |
| `&` | 按位与 | 2 | 两个二进制位都为 1 ,结果为 1 ,否则为 0 。 | ❎ |
| `\|` | 按位或 | 2 | 两个二进制位只要有一个为 1包含两个都为 1 的情况),结果为 1 ,否则为 0 。 | ❎ |
| `^` | 按位异或 | 2 | 两个二进制位一个为 0 ,一个为 1 ,结果为 1否则为 0 。 | ❎ |
| `~` | 按位取反 | 2 | 将每一个二进制位变成相反值,即 0 变成 1 1 变 成 0 。 | ❎ |
| `<<` | 二进制左移 | 2 | 将一个数的各二进制位全部左移指定的位数,左 边的二进制位丢弃,右边补 0。 | ❎ |
| `>>` | 二进制右移 | 2 | 将一个数的各二进制位全部右移指定的位数,正数左补 0负数左补 1右边丢弃。 | ❎ |
> [!NOTE]
>
> 操作数在进行位运算的时候,以它的补码形式计算!!!
### 2.6.2 输出二进制位
* 在 C 语言中,`printf` 是没有提供输出二进制位的格式占位符的;但是,我们可以手动实现,以方便后期操作。
* 示例:
```c
#include <stdio.h>
/**
* 获取指定整数的二进制表示
* @param num 整数
* @return 二进制表示的字符串,不包括前导的 '0b' 字符
*/
char* getBinary(int num) {
static char binaryString[33];
int i, j;
for (i = sizeof(num) * 8 - 1, j = 0; i >= 0; i--, j++) {
const int bit = (num >> i) & 1;
binaryString[j] = bit + '0';
}
binaryString[j] = '\0';
return binaryString;
}
int main() {
int a = 17;
int b = -12;
printf("整数 %d 的二进制表示:%s \n", a, getBinary(a));
printf("整数 %d 的二进制表示:%s \n", b, getBinary(b));
return 0;
}
```
### 2.6.3 按位与
* 按位与 `&` 的运算规则是:如果二进制对应的位上都是 1 才是 1 ,否则为 0 ,即:
* `1 & 1` 的结果是 `1`
* `1 & 0` 的结果是 `0`
* `0 & 1` 的结果是 `0`
* `0 & 0` 的结果是 `0`
* 示例:`9 & 7 = 1`
![](./assets/17.png)
* 示例:`-9 & 7 = 7`
![](./assets/18.png)
### 2.6.4 按位或
* 按位与 `|` 的运算规则是:如果二进制对应的位上只要有 1 就是 1 ,否则为 0 ,即:
* `1 | 1` 的结果是 `1`
* `1 | 0` 的结果是 `1`
* `0 | 1` 的结果是 `1`
* `0 | 0` 的结果是 `0`
* 示例:`9 | 7 = 15`
![](./assets/19.png)
* 示例:`-9 | 7 = -9`
![](./assets/20.png)
### 2.6.5 按位异或
* 按位与 `^` 的运算规则是:如果二进制对应的位上一个为 1 一个为 0 就为 1 ,否则为 0 ,即:
* `1 ^ 1` 的结果是 `0`
* `1 ^ 0` 的结果是 `1`
* `0 ^ 1` 的结果是 `1`
* `0 ^ 0` 的结果是 `0`
> [!NOTE]
>
> 按位异或的场景有:
>
> * ① 交换两个数值:异或操作可以在不使用临时变量的情况下交换两个变量的值。
> * ② 加密或解密:异或操作用于简单的加密和解密算法。
> * ③ 错误检测和校正异或操作可以用于奇偶校验位的计算和检测错误RAID-3 以及以上)。
> * ……
* 示例:`9 ^ 7 = 14`
![](./assets/21.png)
* 示例:`-9 ^ 7 = -16`
![](./assets/22.png)
### 2.6.6 按位取反
* 运算规则:如果二进制对应的位上是 1则结果为 0如果是 0 ,则结果为 1 。
* `~0` 的结果是 `1`
* `~1` 的结果是 `0`
* 示例:`~9 = -10`
![](./assets/23.png)
* 示例:`~-9 = 8`
![](./assets/24.png)
### 2.6.7 二进制左移
* 在一定范围内,数据每向左移动一位,相当于原数据 × 2。正数、负数都适用
* 示例:`3 << 4 = 48` 3 × 2^4
![](./assets/25.png)
* 示例:`-3 << 4 = -48` -3 × 2 ^4
![](./assets/26.png)
### 2.6.8 二进制右移
* 在一定范围内,数据每向右移动一位,相当于原数据 ÷ 2。正数、负数都适用
> [!NOTE]
>
> * ① 如果不能整除,则向下取整。
> * ② 右移运算符最好只用于无符号整数,不要用于负数。因为不同系统对于右移后如何处理负数的符号位,有不同的做法,可能会得到不一样的结果。
* 示例:`69 >> 4 = 4` 69 ÷ 2^4
![](./assets/27.png)
* 示例:`-69 >> 4 = -5` -69 ÷ 2^4
![](./assets/28.png)
## 2.7 三元运算符
* 语法:
```c
条件表达式 ? 表达式1 : 表达式2 ;
```
> [!NOTE]
>
> * 如果条件表达式为非 0 (真),则整个表达式的值是表达式 1 。
> * 如果条件表达式为 0 (假),则整个表达式的值是表达式 2 。
* 示例:
```c
#include <stdio.h>
int main() {
int m = 110;
int n = 20;
int result = m > n ? m : n;
printf("result = %d\n", result); // result = 110
return 0;
}
```
## 2.8 运算符优先级
* C 语言中运算符的优先级,如下所示:
| **优先级** | **运算符** | **名称或含义** | **结合方向** |
| ---------- | ---------- | ---------------- | ------------- |
| **1** | `[]` | 数组下标 | ➡️(从左到右) |
| | `()` | 圆括号 | |
| | `.` | 成员选择(对象) | |
| | `->` | 成员选择(指针) | |
| **2** | `-` | 负号运算符 | ⬅️(从右到左) |
| | `(类型)` | 强制类型转换 | |
| | `++` | 自增运算符 | |
| | `--` | 自减运算符 | |
| | `*` | 取值运算符 | |
| | `&` | 取地址运算符 | |
| | `!` | 逻辑非运算符 | |
| | `~` | 按位取反运算符 | |
| | `sizeof` | 长度运算符 | |
| **3** | `/` | 除 | ➡️(从左到右) |
| | `*` | 乘 | |
| | `%` | 余数(取模) | |
| **4** | `+` | 加 | ➡️(从左到右) |
| | `-` | 减 | |
| **5** | `<<` | 左移 | ➡️(从左到右) |
| | `>>` | 右移 | |
| **6** | `>` | 大于 | ➡️(从左到右) |
| | `>=` | 大于等于 | |
| | `<` | 小于 | |
| | `<=` | 小于等于 | |
| **7** | `==` | 等于 | ➡️(从左到右) |
| | `!=` | 不等于 | |
| **8** | `&` | 按位与 | ➡️(从左到右) |
| **9** | `^` | 按位异或 | ➡️(从左到右) |
| **10** | `\|` | 按位或 | ➡️(从左到右) |
| **11** | `&&` | 逻辑与 | ➡️(从左到右) |
| **12** | `\|\|` | 逻辑或 | ➡️(从左到右) |
| **13** | `?:` | 条件运算符 | ⬅️(从右到左) |
| **14** | `=` | 赋值运算符 | ⬅️(从右到左) |
| | `/=` | 除后赋值 | |
| | `*=` | 乘后赋值 | |
| | `%=` | 取模后赋值 | |
| | `+=` | 加后赋值 | |
| | `-=` | 减后赋值 | |
| | `<<=` | 左移后赋值 | |
| | `>>=` | 右移后赋值 | |
| | `&=` | 按位与后赋值 | |
| | `^=` | 按位异或后赋值 | |
| | `\|=` | 按位或后赋值 | |
| **15** | `,` | 逗号运算符 | ➡️(从左到右) |
> [!WARNING]
>
> * ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量`使用小括号来控制`表达式的执行顺序。
> * ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它`分成几步`来完成。
> * ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。
# 第三章:附录
## 3.1 字符集和字符集编码
### 3.3.1 概述
* 字符集和字符集编码(简称编码)计算机系统中处理文本数据的两个基本概念,它们密切相关但又有区别。
* 字符集Character Set是一组字符的集合其中每个字符都被分配了一个`唯一的编号`(通常是数字)。字符可以是字母、数字、符号、控制代码(如换行符)等。`字符集定义了可以表示的字符的范围`,但它并不直接定义如何将这些字符存储在计算机中。
> [!NOTE]
>
> ASCII美国信息交换标准代码是最早期和最简单的字符集之一它只包括了英文字母、数字和一些特殊字符共 128 个字符。每个字符都分配给了一个从 0 到 127 的数字。
* 字符集编码Character Encoding简称编码是一种方案或方法`它定义了如何将字符集中的字符转换为计算机存储和传输的数据(通常是一串二进制数字)`。简而言之,编码是字符到二进制数据之间的映射规则。
> [!NOTE]
>
> ASCII编码方案定义了如何将 ASCII 字符集中的每个字符表示为 7 位的二进制数字。例如:大写字母`"A"`在ASCII 编码中表示为二进制的`1000001`,十进制的 `65`
* `字符集`和`字符集编码`之间的关系如下:
![](./assets/29.png)
* Linux 中安装帮助手册:
![](./assets/30.gif)
### 3.3.2 ASCII 编码
* 从`冯·诺依曼`体系结构中,我们知道,计算机中所有的`数据`和`指令`都是以`二进制`的形式表示的;所以,计算机中对于文本数据的数据也是以二进制来存储的,那么对应的流程如下:
![](./assets/31.png)
* 我们知道,计算机是上个世纪 60 年代在美国研制成功的,为了实现字符和二进制的转换,美国就制定了一套字符编码,即英语字符和二进制位之间的关系,即 ASCII American Standard Code for Information Interchange编码
- ASCII 编码只包括了英文字符、数字和一些特殊字符,一共 128 个字符,并且每个字符都分配了唯一的数字,范围是 0 - 127。
- ASCII 编码中的每个字符都使用 7 位的二进制数字表示;但是,计算机中的存储的最小单位是 1 B = 8 位,那么最高位统一规定为 0 。
> [!NOTE]
>
> - ① 其实,早期是没有字符集的概念的,只是后来为了解决乱码问题,而产生了字符集的概念。
> - ② 对于英文体系来说,`a-zA-Z0-9`以及一些`特殊字符`一共 `128` 就可以满足实际存储需求;所以,在也是为什么 ASCII 码使用 7 位二进制2^7 = 128 )来存储的。
* 在操作系统中就内置了对应的编码表Linux 也不例外;可以使用如下的命令查看:
```shell
man ascii
```
![](./assets/32.gif)
* 其对应的 ASCII 编码表,如下所示:
![](./assets/33.gif)
* 但是,随着计算机的发展,计算机开始了东征之路,由美国传播到东方:
![](./assets/34.png)
- 先是传播到了欧洲,欧洲在兼容 ASCII 编码的基础上,推出了 ISO8859-1 编码,即:
- ISO8859-1 编码包括基本的拉丁字母表、数字、标点符号,以及西欧语言中特有的一些字符,如:法语中的 `è`、德语中的 `ü` 等。
- ISO 8859-1 为每个字符分配一个单字节8 位)编码,意味着它可以表示最多 256 2^8个不同的字符编号从 0 到 255
- ISO 8859-1 的前 128 个字符与 ASCII 编码完全一致,这使得 ASCII 编码的文本可以无缝转换为 ISO 8859-1 编码。
![](./assets/35.gif)
![](./assets/36.gif)
- 计算机继续传播到了亚洲,亚洲(双字节)各个国家分别给出了自己国家对应的字符集编码,如:
- 日本推出了 Shift-JIS 编码:
- 单字节 ASCII 范围0 - 127。
- 双字节范围:
- 第一个字节129 - 159 和 224 - 239 。
- 第二个字节64 - 126 和 128 - 252 。
- 韩国推出了 EUC-KR 编码:
- 单字节 ASCII 范围0 - 127。
- 双字节范围:从 41281 - 65278。
- 中国推出了 GBK 编码:
- 单字节 ASCII 范围0 - 127。
- 双字节范围33088 - 65278 。
> [!NOTE]
>
> - ① 通过上面日本、韩国、中国的编码十进制范围,我们可以看到,虽然这些编码系统在技术上的编码范围存在重叠(特别是在高位字节区域),但因为它们各自支持的字符集完全不同,所以实际上它们并不直接冲突。
> - ② 但是,如果一个中国人通过 GBK 编码写的文章,通过邮件发送给韩国人,因为韩国和中国在字符集编码上的高位字节有重叠部分,必然会造成歧义。
### 3.3.3 Unicode 编码
- 在 Unicode 之前世界上存在着数百种不同的编码系统每一种编码系统都是为了支持特定语言或一组语言的字符集。这些编码系统包括ASCII、ISO 8859 系列、GBK、Shift-JIS、EUC-KR 等,它们各自有不同的字符范围和编码方式。这种多样性虽然在局部范围内解决了字符表示的问题,但也带来了以下几个方面的挑战:
- `编码冲突`:由于不同的编码系统可以为相同的字节值分配不同的字符,因此在不同编码之间转换文本时,如果没有正确处理编码信息,就很容易产生乱码。这种编码冲突在尝试处理多种语言的文本时尤为突出。
- `编码的复杂性`:随着全球化的发展,软件和系统需要支持越来越多的语言,这就要求开发者和系统同时处理多种不同的编码系统。这不仅增加了开发和维护的复杂性,而且也增加了出错的风险。
- `资源限制`:在早期计算机技术中,内存和存储资源相对有限。不同的编码标准要求系统存储多套字符集数据,这无疑增加了对有限资源的消耗。
- ……
- 针对上述的种种问题为了推行全球化Unicode 应运而生Unicode 的核心规则和设计原则是建立一个全球统一的字符集,使得世界上所有的文字和符号都能被唯一地识别和使用,无论使用者位于何地或使用何种语言。这套规则包括了字符的编码、表示、处理和转换机制,旨在确保不同系统和软件间能够无缝交换和处理文本数据。
- `通用字符集 (UCS)`Unicode 为每一个字符分配一个唯一的编号(称为`“码点”`)。这些码点被组织在一个统一的字符集中,官方称之为 “通用字符集”Universal Character SetUCS。码点通常表示为 `U+` 后跟一个十六进制数,例如:`U+0041` 代表大写的英文字母 `“A”`
- `编码平面和区段`Unicode 码点被划分为多个 “平面Planes每个平面包含 6553616^4个码点。目前Unicode定义了 17 个平面(从 0 到16每个平面被分配了一个编号从 “基本多文种平面BMP” 的 0 开始,到 16 号平面结束。这意味着 Unicode 理论上可以支持超过 110万17*65536个码点。
- Unicode 仅仅只是字符集,给每个字符设置了唯一的数字编号而已,却没有给出这些数字编号实际如何存储,可以通过如下命令查看:
![](./assets/37.gif)
- 为了在计算机系统中表示 Unicode 字符,定义了几种编码方案,这些方案包括 UTF-8、UTF-16 和 UTF-32 等。
- **UTF-8**:使用 1 - 4 个字节表示每个 Unicode 字符,兼容 ASCII是网络上最常用的编码。
- **UTF-16**:使用 2 - 4 个字节表示每个 Unicode 字符,适合于需要经常处理基本多文种平面之外字符的应用。
- **UTF-32**:使用固定的 4 个字节表示每个 Unicode 字符,简化了字符处理,但增加了存储空间的需求。
- `Unicode 字符集`和对应的`UTF-8 字符编码`之间的关系,如下所示:
![](./assets/38.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,1412 @@
# 第一章:概述
* `流程控制结构`是用来控制程序中`各语句执行顺序`的语句,并且可以将语句组合成能`完成一定功能`的`小逻辑模块`。
* 在程序设计中规定了`三种`流程结构,如下所示:
* `顺序结构`:程序从上到下逐行执行,中间没有任何判断和跳转。
* `分支结构`:根据条件,有选择的执行某段代码。在 C 语言中,有 `if...else``switch...case` 两种分支语句。
* `循环结构`:根据循环条件,重复性的执行某段代码。在 C 语言中,有 `for`、`while`、`do...while` 三种循环结构。
* 在生活中的`洗衣工厂`,就包含了上述的三种流程结构,如下所示:
![](./assets/1.jpg)
# 第二章:顺序结构
## 2.1 概述
* 程序从上到下逐行地执行,表达式语句都是顺序执行的,并且上一行对某个变量的修改对下一行会产生影响。
![](./assets/2.png)
## 2.2 应用示例
* 示例:
```c
#include <stdio.h>
int main() {
int x = 1;
int y = 2;
printf("x = %d \n", x); // x = 1
printf("y = %d \n", y); // y = 2
// 对 x 和 y 的值进行修改
x++;
y = 2 * x + y;
x = x * 10;
printf("x = %d \n", x); // x = 20
printf("y = %d \n", y); // y = 6
return 0;
}
```
# 第三章:分支结构(⭐)
## 3.1 概述
* 根据特定条件执行不同的代码块,从而实现灵活的程序控制和更复杂的逻辑。
## 3.2 单分支结构
### 3.2.1 概述
* 语法:
```c
if(条件表达式){
语句;
}
```
> [!NOTE]
>
> * ① 在 C 语言中,严格意义上是没有 boolean 类型的,使用`非0` 表示`真true``0` 表示`假false`。
> * ② 当条件表达式为真(`非0` ),就会执行代码块中的语句;否则,就不会执行代码块中的语句。
* 流程图,如下所示:
![](./assets/3.png)
### 3.2.2 应用示例
* 需求:成年人心率的正常范围是每分钟 60~100 次。体检时,如果心率不在此范围内,则提示需要做进一步的检查。
* 示例:
```c
#include <stdio.h>
int main() {
int heartBeats = 0;
printf("请输入您的心率:");
scanf("%d", &heartBeats);
if (heartBeats < 60 || heartBeats > 100) {
printf("您的心率不在正常范围内,请做进一步的检查。\n");
}
printf("体检结束!!!");
return 0;
}
```
### 3.2.3 应用示例
* 需求:根据年龄判断,如果是未成年人,则提示 "未成年人请在家长陪同下访问!" 。
* 示例:
```c
#include <stdio.h>
int main() {
int age = 0;
printf("请输入你的年龄:");
scanf("%d", &age);
if (age < 18) {
printf("未成年人请在家长陪同下访问!\n");
}
printf("欢迎继续访问!");
return 0;
}
```
## 3.3 双分支结构
### 3.3.1 概述
* 语法:
```c
if(条件表达式) {
语句块1;
}else {
语句块2;
}
```
> [!NOTE]
>
> * ① 在 C 语言中,严格意义上是没有 boolean 类型的,使用`非0` 表示`真true``0` 表示`假false`。
> * ② 当条件表达式为真(`非0` ),就会执行代码块 1 中的语句;否则,执行代码块 2 中的语句。
* 流程图,如下所示:
![](./assets/4.png)
### 3.3.2 应用示例
* 需求:判断一个整数,是奇数还是偶数。
* 示例:
```c
#include <stdio.h>
int main() {
int num = 0;
printf("请输入一个整数:");
scanf("%d", &num);
if (num % 2 == 0) {
printf("%d 是偶数\n", num);
} else {
printf("%d 是奇数\n", num);
}
return 0;
}
```
### 3.3.2 应用示例
* 需求输入年龄如果大于18岁则输出 "你年龄大于18要对自己的行为负责!";否则,输出 "你的年龄不大这次放过你了。"
* 示例:
```c
#include <stdio.h>
int main() {
int age = 0;
printf("请输入年龄:");
scanf("%d", &age);
if (age > 18) {
printf("你年龄大于18要对自己的行为负责!\n");
} else {
printf("你的年龄不大,这次放过你了!\n");
}
return 0;
}
```
### 3.3.3 应用示例
* 需求:判定某个年份是否为闰年?
>[!NOTE]
>
>* ① year 是 400 的整倍数: year%400==0
>* ② 能被 4 整除,但不能被 100 整除year % 4 == 0 && year % 100 != 0
* 示例:
```c
#include <stdio.h>
int main() {
int year = 0;
printf("请输入年份:");
scanf("%d", &year);
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
printf("%d 是闰年\n", year);
} else {
printf("%d 不是闰年\n", year);
}
return 0;
}
```
## 3.4 多重分支结构
### 3.4.1 概述
* 语法:
```c
if (条件表达式1) {
语句块1;
} else if (条件表达式2) {
语句块2;
}
...
} else if (条件表达式n) {
语句块n;
} else {
语句块n+1;
}
```
> [!NOTE]
>
> * ① 在 C 语言中,严格意义上是没有 boolean 类型的,使用`非0` 表示`真true``0` 表示`假false`。
> * ② 首先判断关系表达式 1 的结果是真(值为 `非0`)还是假(值为 `0`
> * 如果为真,就执行语句块 1然后结束当前多分支。
> * 如果是假,就继续判断条件表达式 2看其结果是真还是假。
> * 如果是真,就执行语句块 2然后结束当前多分支。
> * 如果是假,就继续判断条件表达式…看其结果是真还是假。
> * ...
> * 如果没有任何关系表达式为真,就执行语句块 n+1然后结束当前多分支。
> * ③ 当条件表达式之间是`互斥`(彼此之间没有交集)关系时,条件判断语句及执行语句间顺序无所谓。
> * ④ 当条件表达式之间是`包含`关系时,必须`小上大下 / 子上父下`,否则范围小的条件表达式将不可能被执行。
> * ⑤ 当 if-else 结构是多选一的时候,最后的 else 是可选的,可以根据需要省略。
> * ⑥ 如果语句块中只有一条执行语句的时候,`{}`是可以省略的;但是,强烈建议保留!!!
* 流程图,如下所示:
![image-20240722075241253](./assets/5.png)
### 3.4.1 应用示例
* 需求:张三参加考试,他和父亲达成协议,如果成绩不到 60 分没有任何奖励;如果成绩 60分到 80 分,奖励一个肉夹馍;如果成绩 80 分(含)到 90 分,奖励一个 ipad如果成绩 90 分及以上,奖励一部华为 mate60 pro 。
* 示例:
```c
#include <stdio.h>
int main() {
int score = 0;
printf("请输入分数:");
scanf("%d", &score);
// 容错:分数不可能小于 0 或大于 100
if (score < 0 || score > 100) {
printf("输入的分数有误!\n");
return 0;
}
if (score >= 90) {
printf("奖励你一部华为 mate60 pro\n");
} else if (score >= 80) {
printf("奖励你一个 ipad\n");
} else if (score >= 60) {
printf("奖励你一个肉夹馍\n");
} else {
printf("你的成绩不及格,没有任何奖励!");
}
return 0;
}
```
### 3.4.2 应用示例
* 需求:判断水的温度,如果大于 95℃则打印 "开水";如果大于 70℃ 且小于等于 95℃则打印 "热水";如果大于 40℃ 且小于等于 70℃则打印 "温水";如果小于等于 40℃则打印 "凉水"。
* 示例:
```c
#include <stdio.h>
int main() {
int temperature = 0;
printf("请输入水的温度:");
scanf("%d", &temperature);
if (temperature > 95) {
printf("开水 \n");
} else if (temperature > 70 && temperature <= 95) {
printf("热水 \n");
} else if (temperature > 40 && temperature <= 70) {
printf("温水 \n");
} else {
printf("凉水 \n");
}
return 0;
}
```
## 3.5 多重分支结构 switch
### 3.5.1 概述
* 语法:
```c
switch(表达式){
case 常量值1:
语句块1;
//break;
case 常量值2:
语句块2;
//break;
...
case 常量值n:
语句块n;
//break;
[default:
语句块n+1;
]
}
```
> [!NOTE]
>
> * ① switch 后面表达式的值必须是一个整型char、short、int、long 等)或枚举类型。
> * ② case 后面的值必须是常量,不能是变量。
> * ③ default 是可选的,当没有匹配的 case 的时候,就执行 default 。
> * ④ break 语句可以使程序跳出 switch 语句块,如果没有 break会执行下一个 case 语句块,直到遇到 break 或者执行到 switch 结尾,这个现象称为穿透。
* 流程图,如下所示:
![](./assets/6.png)
### 3.5.2 应用示例
* 需求编写一个程序该程序可以接收一个字符比如a、b、c、d其中 a 表示星期一b 表示星期二…,根据用户的输入显示相应的信息,要求使用 switch 语句。
* 示例:
```c
#include <stdio.h>
int main() {
char chs;
printf("请输入一个字符a、b、c、d");
scanf("%c", &chs);
switch (chs) {
case 'a':
printf("今天是星期一 \n");
printf("窗前明月光 \n");
break;
case 'b':
printf("今天是星期二 \n");
printf("疑是地上霜 \n");
break;
case 'c':
printf("今天是星期三 \n");
printf("举头望明月 \n");
break;
case 'd':
printf("今天是星期四 \n");
printf("低头思故乡 \n");
break;
default:
printf("输入错误!");
break;
}
return 0;
}
```
### 3.5.3 应用示例
* 需求编写程序输入月份输出该月份有多少天。说明1 月、3 月、5 月、7月、8 月、10 月、12 月有 31 天4 月、6 月、9 月、11 月有 30 天2 月有 28 天或 29 天。
* 示例:
```c
#include <stdio.h>
int main() {
int month;
printf("请输入月份 (1-12)");
scanf("%d", &month);
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
printf("%d 月有 31 天\n", month);
break;
case 4:
case 6:
case 9:
case 11:
printf("%d 月有 30 天\n", month);
break;
case 2:
printf("%d 月有 28 天或 29 天\n", month);
break;
default:
printf("输入错误!");
break;
}
return 0;
}
```
### 3.5.4 switch 和 if else if 的比较
* ① 如果判断条件是判等,而且符合整型、枚举类型,虽然两个语句都可以使用,建议使用 swtich 语句。
* ② 如果判断条件是区间判断,大小判断等,使用 if...else...if。
## 3.6 嵌套分支
### 3.6.1 概述
* 嵌套分支是指,在一个分支结构中又嵌套了另一个分支结构,里面的分支的结构称为内层分支,外面的分支结构称为外层分支。
> [!NOTE]
>
> 嵌套分支层数不宜过多,建议最多不要超过 3 层。
### 3.6.2 应用示例
* 需求:根据淡旺季的月份和年龄,打印票价。
> [!NOTE]
>
> * ① 4 -10 是旺季:
> * 成人18-6060 。
> * 儿童(<18半价
> * 老人(>601/3 。
> * ② 其余是淡季:
> * 成人40。
> * 其他20。
* 示例:
```c
#include <stdio.h>
int main() {
int month;
int age;
double price = 60;
printf("请输入月份 (1-12)");
scanf("%d", &month);
printf("请输入年龄:");
scanf("%d", &age);
// 旺季
if (month >= 4 && month <= 10) {
if (age < 18) {
price /= 2;
} else if (age > 60) {
price /= 3;
}
} else {
if (age >= 18) {
price = 40;
} else {
price = 20;
}
}
printf("票价: %.2lf\n", price);
return 0;
}
```
# 第四章:随机数
## 4.1 概述
* 所谓的随机数就是没有规则,并且不能预测的一些数字,也称为真随机数。
* 程序中也是可以产生随机数的,但是是通过一些固定规则产生的,称为伪随机数。
* 常见的伪随机数线性同余发生器LCG的公式如下所示
$[ X_{n+1} = (a \cdot X_n + c) \mod m ]$
* 其中X 是伪随机序列a 是乘数(通常选择一个大于 0 的常数,典型值有 1664525c 是增量选择一个大于0的常数典型值有1013904223 m 是模数( 通常选择一个大的常数,常见值有 ( 2^{32} ) ,即 4294967296
* 工作原理:
* ① 设置初始种子X_0
* 种子值是算法生成随机数序列的起点。
* 不同的种子值会产生不同的随机数序列。
* ② 递归生成随机数:
* 从初始种子开始,通过公式不断生成新的随机数。
* 每次迭代都使用前一次生成的随机数作为输入。
> [!NOTE]
>
> 如果种子的值相同,那么每次生成的随机数将相同,解决方案就是将种子的值设置为当前的时间戳。
## 4.2 C 语言中随机数的产生
* ① 设置随机数种子:
```c
srand(10); // seed 种⼦ rand random 随机
```
> [!NOTE]
>
> 随机数函数在 `#include <stdlib.h>` 中声明。
* ② 根据随机数种⼦计算出⼀个伪随机数:
```c
// 根据种⼦值产⽣⼀个 0-32767 范围的随机数
int result = rand();
```
* ③ 产生一个指定范围内的随机数:
```c
int random_in_range(int min, int max) {
return rand() % (max - min + 1) + min;
}
```
* 示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 生成指定范围的随机数的函数
int randomInRange(int min, int max) {
return rand() % (max - min + 1) + min;
}
int main() {
// 使用当前时间作为种子
srand(time(0));
// 定义范围
int min = 1;
int max = 100;
// 生成并打印随机数
for (int i = 0; i < 10; ++i) {
int random = randomInRange(min, max);
printf("%d \n", random);
}
return 0;
}
```
# 第五章:循环结构(⭐)
## 5.1 概述
* 循环结构:在某些条件满足的情况下,反复执行特定代码的功能。
## 5.2 for 循环
### 5.2.1 概述
* 语法:
```c
for(初始化条件①;循环条件表达式②;迭代语句④){
循环体语句③
}
```
> [!NOTE]
>
> * ① 初始化条件,用于初始化循环变量,只会执行一次,且循环开始前就执行(可以声明多个变量,但是必须是同一类型,用逗号 `,` 隔开)。
> * ② 循环条件表达式每次循环都执行,同 while 循环一样,每次先判断后执行循环体语句。
> * ③ 迭代语句每次循环都执行,在大括号中循环体语句之后执行(如果有多个变量更新,用逗号 `,` 隔开)。
* 流程图,如下所示:
![](./assets/7.png)
> [!NOTE]
>
> 执行过程是:① --> ② --> ③ --> ④ --> ② --> ③ --> ④ --> ... --> ② 。
### 5.2.2 应用示例
* 需求:输出 5 行 `Hello World!`
* 示例:
```c
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; ++i) {
printf("Hello World!\n");
}
return 0;
}
```
### 5.2.3 应用示例
* 需求:求 1 ~ 100 之内所有偶数的和,以及偶数的个数。
* 示例:
```c
#include <stdio.h>
int main() {
int sum = 0;
int count = 0;
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
sum += i;
count++;
}
}
printf("1 ~ 100 中的所有偶数的和为: %d \n", sum);
printf("1 ~ 100 中的所有偶数的个数为: %d \n", count);
return 0;
}
```
### 5.2.4 应用示例
* 需求:输出所有的水仙花数,所谓水仙花数是指一个 3 位数,其各个位上数字立方和等于其本身,例如:`153 = 1×1×1 + 3×3×3 + 5×5×5`。
* 示例:
```c
#include <stdio.h>
int main() {
int count = 0;
for (int i = 100; i <= 999; i++) {
// 获取三位数
int ge = i % 10;
int shi = i / 10 % 10;
int bai = i / 100;
// 判定是否为水仙花数
if (ge * ge * ge + shi * shi * shi + bai * bai * bai == i) {
printf("水仙花数:%d\n", i);
count++;
}
}
printf("水仙花数总个数:%d\n", count);
return 0;
}
```
### 5.2.5 应用示例
* 需求:将 1 ~ 10 倒序输出10 、9 、8 ...
* 示例:
```c
#include <stdio.h>
int main() {
for (int i = 10; i >= 0; i--) {
printf("%d ", i);
}
return 0;
}
```
### 5.2.6 应用示例
* 需求:输入两个正整数 m 和 n 求其最大公约数和最小公倍数例如12 和 20 的最大公约数是 4 ,最小公倍数是 60 。
> [!NOTE]
>
> * 如果数 a 能被数 b 整除,且结果是整数,那么 a 就叫做 b 的倍数b 就叫做 a 的约数(因数)。
> * 如果一个整数同时是几个整数的约数,则称该整数为这些整数的公约数;其中,数值最大的称为最大公约数。
> * 如果一个整数同时为两个或多个整数的倍数的数,则称该整数为这些整数的公倍数;其中,数值最小的称为最小公倍数。
* 示例:
```c
#include <stdio.h>
int main() {
int m = 12, n = 20;
// 取出两个数中的较小值
int min = (m < n) ? m : n;
for (int i = min; i >= 1; i--) {
if (m % i == 0 && n % i == 0) {
printf("最大公约数是:%d\n", i); // 公约数
break; //跳出当前循环结构
}
}
// 取出两个数中的较大值
int max = (m > n) ? m : n;
for (int i = max; i <= m * n; i++) {
if (i % m == 0 && i % n == 0) {
printf("最小公倍数是:%d\n", i); // 公倍数
break;
}
}
return 0;
}
```
## 5.3 while 循环
### 5.3.1 概述
* 语法:
```c
初始化条件①;
while (循环条件语句②) {
循环体语句③;
迭代语句④;
}
```
> [!NOTE]
>
> * ① `while(循环条件部分)` 中循环条件为`非0`值,表示 `true`、`真`;为`0`值,表示 `false`、`假`。
> * ② 当循环条件表达式成立,就执行循环体语句,直到条件不成立停止循环。
> * ③ 为避免死循环,循环条件表达式不能永远成立,且随着循环次数增加,应该越来越趋向于不成立。
> * ④ for 循环和 while 循环`可以相互转换`,二者没有性能上的差别。
> * ⑤ for 循环与 while 循环的区别:`初始化条件部分的作用域不同`。
* 流程图,如下所示:
![](./assets/8.png)
> [!NOTE]
>
> 执行过程是:① --> ② --> ③ --> ④ --> ② --> ③ --> ④ --> ... --> ② 。
### 5.3.2 应用示例
* 需求:输出 5 行 `Hello World!`
* 示例:
```c
#include <stdio.h>
int main() {
int i = 1;
while (i <= 5) {
printf("Hello World!\n");
i++;
}
return 0;
}
```
### 5.3.3 应用示例
* 需求:求 1 ~ 100 之内所有偶数的和,以及偶数的个数。
* 示例:
```c
#include <stdio.h>
int main() {
int sum = 0;
int count = 0;
int i = 1;
while (i <= 100) {
if (i % 2 == 0) {
sum += i;
count++;
}
i++;
}
printf("1 ~ 100 中的所有偶数的和为: %d \n", sum);
printf("1 ~ 100 中的所有偶数的个数为: %d \n", count);
return 0;
}
```
### 5.3.4 应用示例
* 需求:世界最高山峰是珠穆朗玛峰,它的高度是 8848.86 米,假如我有一张足够大的纸,它的厚度是 0.1 毫米。请问,我折叠多少次,可以折成珠穆朗玛峰的高度?
* 示例:
```c
#include <stdio.h>
int main() {
// 折叠的次数
int count = 0;
// 珠峰的高度
int zfHeight = 8848860;
// 每次折叠的高度
double paperHeight = 0.1;
while (paperHeight <= zfHeight) {
count++;
paperHeight *= 2;
}
printf("需要折叠 %d 次,才能得到珠峰的高度。\n", count);
printf("折纸的高度为 %.2f 米,超过了珠峰的高度", paperHeight / 1000);
return 0;
}
```
## 5.4 do-while 循环
### 5.4.1 概述
* 语法:
```c
①初始化部分;
do{
③循环体部分
④迭代部分
}while(②循环条件部分);
```
> [!NOTE]
>
> * ① `do{} while();`最后有一个分号。
> * ② do-while 结构的循环体语句是至少会执行一次,这个和 for 、while 是不一样的。
> * ③ 循环的三个结构 for、while、do-while 三者是可以相互转换的。
* 流程图,如下所示:
![](./assets/9.png)
> [!NOTE]
>
> 执行过程是:① --> ③ --> ④ --> ② --> ③ --> ④ --> ② --> ... --> ② 。
### 5.4.2 应用示例
* 需求:求 1 ~ 100 之内所有偶数的和,以及偶数的个数。
```c
#include <stdio.h>
int main() {
int sum = 0;
int count = 0;
int i = 1;
do {
if (i % 2 == 0) {
sum += i;
count++;
}
i++;
} while (i <= 100);
printf("1 ~ 100 中的所有偶数的和为: %d \n", sum);
printf("1 ~ 100 中的所有偶数的个数为: %d \n", count);
return 0;
}
```
### 5.4.3 应用示例
* 需求:实现 ATM 取款机功能。
* 示例:
```c
#include <stdio.h>
int main() {
// 账户余额
double balance = 0.0;
// 客户选择
int selection;
// 存款金额
double addMoney;
// 取款金额
double minusMoney;
// 退出标识
bool exitFlag = false;
do {
printf("=========ATM========\n");
printf("\t1、存款\n");
printf("\t2、取款\n");
printf("\t3、显示余额\n");
printf("\t4、退出\n");
printf("请选择(1-4)");
scanf("%d", &selection);
switch (selection) {
case 1:
printf("您当前的余额是: %.2f\n", balance);
printf("请输入存款金额:");
scanf("%lf", &addMoney);
balance += addMoney;
printf("存款成功,您当前的余额是:%.2f\n", balance);
break;
case 2:
printf("您当前的余额是: %.2f\n", balance);
printf("请输入取款金额:");
scanf("%lf", &minusMoney);
if (minusMoney > balance) {
printf("余额不足,取款失败。\n");
} else {
balance -= minusMoney;
printf("取款成功,您的余额为:%.2f\n", balance);
}
break;
case 3:
printf("您的账户余额为:%.2f\n", balance);
break;
case 4:
exitFlag = true;
printf("欢迎下次再来。\n");
break;
default:
printf("输入有误,请重新输入。\n");
break;
}
} while (!exitFlag);
return 0;
}
```
## 5.5 嵌套循环
### 5.5.1 概述
* 所谓的嵌套循环,是指一个循环结构 A 的循环体是另一个循环结构 B 。例如for 循环里面还有一个for 循环,就是嵌套循环。
* 语法:
```c
for(初始化语句①; 循环条件语句②; 迭代语句⑦) {
for(初始化语句③; 循环条件语句④; 迭代语句⑥) {
循环体语句⑤;
}
}
```
* 其中for 、while 、do-while 均可以作为外层循环或内层循环。
- 外层循环:循环结构 A
- 内层循环:循环结构 B
![](./assets/10.png)
> [!NOTE]
>
> * ① 实际上,嵌套循环就是将内层循环当成外层循环的循环体。当只有内层循环的循环条件为 false ,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次循环。
> * ② 假设外层循环次数为 m 次,内层循环次数为 n 次,则内层循环体实际上需要执行 m × n 次。
> * ③ 从二维图形的角度看,外层循环控制`行数`,内层循环控制`列数`。
> * ④ 实际开发中,我们最多见到的嵌套循环是两层,一般不会出现超过三层的嵌套循环。如果将要出现,一定要停下来重新梳理业务逻辑,重新思考算法的实现,控制在三层以内;否则,可读性会很差。
### 5.5.2 应用示例
* 需求:打印 5 行 `*` ,要求每行 6 个 `*`
* 示例:
```c
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; ++i) {
for (int j = 1; j < 6; ++j) {
printf("* ");
}
printf("\n");
}
return 0;
}
```
### 5.5.3 应用示例
* 需求:打印 5 行直角三角形。
* 示例:
```c
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; ++i) {
for (int j = 1; j <= i; ++j) {
printf("* ");
}
printf("\n");
}
return 0;
}
```
### 5.5.4 应用示例
* 需求:打印 5 行倒直角三角形。
* 示例:
```c
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; ++i) {
for (int j = 1; j <= 6 - i; ++j) {
printf("* ");
}
printf("\n");
}
return 0;
}
```
### 5.5.5 应用示例
* 需求:打印 9 `×` 9 乘法表。
* 示例:
```c
#include <stdio.h>
int main() {
for (int i = 1; i <= 9; ++i) {
for (int j = 1; j <= i; ++j) {
printf("%d × %d = %d ", i, j, i * j);
}
printf("\n");
}
return 0;
}
```
## 5.6 无限循环
* 语法:
```c
while(1){
...
}
```
```c
for(;;){
...
}
```
> [!NOTE]
>
> * ① 在开发中有的时候并不确定需要循环多少次就需要根据循环体内部的某些条件来控制循环的结束break
> * ② 如果上述的循环结构不能终止,就会构成死循环;所以,在实际开发中,要避免出现死循环!!!
* 示例:从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为 0 时结束程序
```c
#include <stdio.h>
int main() {
// 记录输入的整数
int num = 0;
// 记录正数个数
int positiveCount = 0;
// 记录负数个数
int negativeCount = 0;
while (true) {
printf("请输入一个整数:");
scanf("%d", &num);
if (num > 0) {
positiveCount++;
} else if (num < 0) {
negativeCount++;
} else {
printf("程序结束!\n");
break;
}
}
printf("正数的个数:%d\n", positiveCount);
printf("负数的个数:%d\n", negativeCount);
return 0;
}
```
## 5.7 跳转控制语句
### 5.7.1 break
* break 的使用场景break 语句用于终止某个语句块的执行用在switch语句或者循环语句中。
> [!NOTE]
>
> break 一旦执行,就结束(或跳出)当前循环结构;并且,此关键字的后面,不能声明其它语句。
* 流程图,如下所示:
![](./assets/11.png)
* 示例:打印 0 ~ 10 ,如果遇到 `3` ,就停止打印
```c
#include <stdio.h>
int main() {
for (int i = 0; i < 10; ++i) {
if (i == 3) {
break;
}
printf("%d \n", i);
}
printf("程序结束!\n");
return 0;
}
```
* 示例:编写程序,要求输入一个数字,判断该数字是否是质数
```c
#include <stdio.h>
int main() {
bool isFlag = false;
int num = 0;
do {
printf("请输入一个整数(必须大于 1 ");
scanf("%d", &num);
if (num <= 1) {
printf("输入的数字不是合法,请重新输入!!!\n");
isFlag = true;
} else {
isFlag = false;
}
} while (isFlag);
bool isPrime = true;
for (int i = 2; i < num; i++) {
if (num % i == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
printf("%d 是一个质数\n", num);
} else {
printf("%d 不是一个质数\n", num);
}
printf("程序结束!\n");
return 0;
}
```
### 5.7.2 continue
* continue 的使用场景continue 语句用于结束本次循环,继续执行下一次循环。
> [!NOTE]
>
> continue 一旦执行,就结束(或跳出)当次循环结构;并且,此关键字的后面,不能声明其它语句。
* 流程图,如下所示:
![](./assets/12.png)
* 示例:打印 0 ~ 10 ,如果遇到 `3` ,就继续下一次打印
```c
#include <stdio.h>
int main() {
for (int i = 0; i < 10; ++i) {
if (i == 3) {
continue;
}
printf("%d \n", i);
}
printf("程序结束!\n");
return 0;
}
```
* 示例:输出 100 以内(包括 100的数字跳过那些 7 的倍数或包含 7 的数字
```c
#include <stdio.h>
int main() {
for (int i = 1; i <= 100; i++) {
if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7) {
continue;
}
printf("%d ", i);
}
printf("程序结束!\n");
return 0;
}
```
### 5.7.3 return
* return :并非专门用于结束循环的,它的功能是结束一个方法。当一个方法执行到一个 return 语句的时候,这个方法将被结束。
> [!NOTE]
>
> 和 break 和 continue 不同的是return 直接结束整个方法,不管这个 return 处于多少层循环之内。
* 示例:
```c
#include <stdio.h>
int main() {
for (int i = 1; i <= 100; i++) {
if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7) {
return 0; // 结束整个函数或方法
}
printf("%d ", i);
}
printf("程序结束!\n");
return 0;
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -0,0 +1,1246 @@
# 第一章:数组的概念
## 1.1 为什么需要数组?
### 1.1.1 需求分析 1
* 需要统计某公司 50 个员工的工资情况,例如:计算平均工资、最高工资等。如果使用之前的知识,我们需要声明 50 个变量来分别记录每位员工的工资,即:
```c
#include <stdio.h>
int main(){
double num1 = 0;
double num2 = 0;
double num3 = 0;
...
printf("请输入第 1 个员工的工资:");
scanf("%lf",&num1);
printf("请输入第 2 个员工的工资:");
scanf("%lf",&num2);
printf("请输入第 3 个员工的工资:");
scanf("%lf",&num3);
...
return 0;
}
```
* 这样会感觉特别机械和麻烦全是复制Ctrl + c和粘贴Ctrl + vCV 大法);此时,我们就可以将所有的`数据`全部存储到一个`容器(数组)`中进行统一管理,并进行其它的操作,如:求最值、求平均值等,如下所示:
```c
#include <stdio.h>
int main(){
// 声明数组
double nums[50];
// 数组的长度
int length = sizeof(nums) / sizeof(double);
// 使用 for 循环向数组中添加值
for(int i = 0;i < length;i++){
printf("请输入第 &d 个员工的工资:",i);
scanf("%lf",&num[i]);
}
// 其它操作,如:求最值,求平均值等
...
return 0;
}
```
### 1.1.2 需求分析 2
* 在现实生活中,我们会使用很多 APP 或微信小程序等,即:
![](./assets/1.png)
* 同样的道理,如果我们使用变量来存储每个商品信息,那么就需要非常多的变量;但是,如果我们将这些`商品信息`都存储到一个`容器(数组)`中,进行统一管理;那么,之后的数据处理将会非常方便。
### 1.1.3 容器的概念
* `生活中的容器`:水杯(装水、饮料的容器)、衣柜(装衣服等物品的容器)、集装箱(装货物等物品的容器)。
* `程序中的容器`:将多个数据存储到一起,并且每个数据称为该容器中的元素。
## 1.2 什么是数组?
* 数组Array是将多个`相同数据类型`的`数据`按照一定的顺序排序的`集合`,并使用一个`标识符`命名,以及通过`编号(索引,亦称为下标)`的方式对这些数据进行统一管理。
![](./assets/2.png)
## 1.3 数组的相关概念
* `数组名`:本质上是一个标识符常量,命名需要符合标识符规则和规范。
* `元素`:同一个数组中的元素必须是相同的数据类型。
* `索引(下标)`:从 0 开始的连续数字。
* `数组的长度`:就是元素的个数。
## 1.4 数组的特点
* ① 创建数组的时候,会在内存中开辟一整块`连续的空间`,占据空间的大小,取决于数组的长度和数组中元素的类型。
* ② 数组中的元素在内存中是依次紧密排列且有序的。
* ③ 数组一旦初始化完成,且长度就确定的,并且`数组的长度一旦确定,就不能更改`。
* ④ 我们可以直接通过索引(下标)来获取指定位置的元素,速度很快。
* ⑤ 数组名中引用的是这块连续空间的首地址。
# 第二章:数组的操作(⭐)
## 2.1 数组的定义
### 2.1.1 动态初始化
* 语法:
```c
数据类型 数组名[元素个数|长度];
```
> [!NOTE]
>
> * ① 数据类型:表示的是数组中每一个元素的数据类型。
> * ② 数组名:必须符合标识符规则和规范。
> * ③ 元素个数或长度:表示的是数组中最多可以容纳多少个元素(不能是负数、也不能是 0 )。
* 示例:
```c
#include <stdio.h>
int main() {
// 先指定元素的个数和类型,再进行初始化
// 定义数组
int arr[3];
// 给数组元素赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
return 0;
}
```
### 2.1.2 静态初始化 1
* 语法:
```c
数据类型 数组名[元素个数|长度] = {元素1,元素2,...}
```
> [!NOTE]
>
> * ① 静态部分初始化:如果数组初始化的元素个数`小于`数组声明的长度,那么就会从数组开始位置依次赋值,不够的就补 0 。
> * ② 静态全部初始化:数组初始化的元素个数`等于`数组的长度。
* 技巧:
* 在 CLion 中可以开启`聚合初始化`功能,即:
![](./assets/3.png)
* 这样,在 CLion 中,将会显示数组初始化中的元素索引,即:
![](./assets/4.png)
* 示例:静态部分初识化
```c
#include <stdio.h>
int main() {
// 定义数组和部分初始化:
// 会将给定的值从数组的开始位置一个个的赋值,没有赋值的地方,用 0 填充
int arr[5] = {1, 2};
return 0;
}
```
* 示例:静态全部初始化
```c
#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[5] = {1, 2, 3, 4, 5};
return 0;
}
```
### 2.1.3 静态初始化 2
* 语法:
```c
数据类型 数组名[] = {元素1,元素2,...}
```
> [!NOTE]
>
> 没有给出数组中元素的个数,将由系统根据初始化的元素,自动推断出数组中元素的个数。
* 示例:
```c
#include <stdio.h>
int main() {
// 指定元素的类型,不指定元素个数,同时进行初始化
int arr[] = {1, 2, 3, 4, 5};
return 0;
}
```
## 2.2 访问数组元素
* 语法:
```c
数组名[索引|下标];
```
> [!NOTE]
>
> 假设数组 `arr` 有 n 个元素,如果使用的数组的下标 `< 0``> n-1` ,那么将会产生数组越界访问,即超出了数组合法空间的访问;那么,数组的索引范围是 `[0,arr.length - 1]`
* 示例:
```c
#include <stdio.h>
int main() {
// 先指定元素的个数和类型,再进行初始化
// 定义数组
int arr[3];
// 给数组元素赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
// 访问数组元素
printf("arr[0] = %d\n", arr[0]); // arr[0] = 10
printf("arr[1] = %d\n", arr[1]); // arr[1] = 20
printf("arr[2] = %d\n", arr[2]); // arr[2] = 30
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
// 定义数组和部分初始化:
// 会将给定的值从数组的开始位置一个个的赋值,没有赋值的地方,用 0 填充
int arr[5] = {1, 2};
// 访问数组元素
printf("arr[0] = %d\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\n", arr[2]); // arr[2] = 0
printf("arr[3] = %d\n", arr[3]); // arr[3] = 0
printf("arr[4] = %d\n", arr[4]); // arr[4] = 0
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
// 指定元素的类型,不指定元素个数,同时进行初始化
int arr[] = {1, 2, 3, 4, 5};
// 访问数组元素
printf("arr[0] = %d\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\n", arr[2]); // arr[2] = 3
printf("arr[3] = %d\n", arr[3]); // arr[3] = 4
printf("arr[4] = %d\n", arr[4]); // arr[4] = 5
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[5] = {1, 2, 3, 4, 5};
// 访问数组元素
printf("arr[0] = %d\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\n", arr[2]); // arr[2] = 3
printf("arr[3] = %d\n", arr[3]); // arr[3] = 4
printf("arr[4] = %d\n", arr[4]); // arr[4] = 5
return 0;
}
```
## 2.3 数组越界
* 数组下标必须在指定范围内使用,超出范围视为越界。
![](./assets/5.png)
> [!NOTE]
>
> * ① C 语言是不会做数组下标越界的检查,并且编译器也不会报错;但是,编译器不报错,并不意味着程序就是正确!
> * ② 在其它高级编程语言Java、JavaScript、Rust 等中,如果数组越界访问,编译器是会直接报错的!!!
* 示例:
```c
#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[] = {1, 2, 3, 4, 5};
// 访问数组元素
printf("arr[0] = %d\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\n", arr[2]); // arr[2] = 3
printf("arr[3] = %d\n", arr[3]); // arr[3] = 4
printf("arr[4] = %d\n", arr[4]); // arr[4] = 5
printf("arr[-1] = %d\n", arr[-1]); // 得到的是不确定的结果
printf("arr[5] = %d\n", arr[5]); // 得到的是不确定的结果
return 0;
}
```
## 2.4 计算数组的长度
* 数组长度(元素个数)是在数组定义的时候明确指定且固定的,我们不能在运行的时候直接获取数组长度;但是,我们可以通过 sizeof 运算符间接计算出数组的长度。
* 计算步骤,如下所示:
* ① 使用 sizeof 运算符计算出整个数组的字节长度。
* ② 由于数组成员是同一数据类型;那么,每个元素的字节长度一定相等,那么`数组的长度 = 整个数组的字节长度 ÷ 单个元素的字节长度 `。
![](./assets/6.png)
> [!NOTE]
>
> * ① 在很多编程语言中都内置了获取数组的长度的属性或方法Java 中的 arr.length 或 Rust 的 arr.len()。
> * ② 但是C 语言没有内置的获取数组长度的属性或方法,只能通过 sizeof 运算符间接来计算得到。
> * ③ 数组一旦`声明`或`定义`,其`长度`就`固定`了,`不能动态变化`。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[] = {1, 2, 3, 4, 5};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(arr[0]);
// 遍历数组
for (int i = 0; i < length; i++) {
printf("%d \n", arr[i]);
}
return 0;
}
```
## 2.5 遍历数组
* 遍历数组是指按顺序访问数组中的每个元素,以便读取或修改它们,编程中一般使用循环结构对数组进行遍历。
* 示例:声明一个存储有 12、2、31、24、15、36、67、108、29、51 的数组,并遍历数组所有元素
```c
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 15, 36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 遍历数组
for (int i = 0; i < length; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
```
* 示例:声明长度为 10 的 int 类型数组,给数组元素依次赋值为 0 ~ 9 ,并遍历数组所有元素
```c
#include <stdio.h>
int main() {
// 定义数组
int arr[10];
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 给数组的每个元素赋值
for (int i = 0; i < length; i++) {
arr[i] = i;
}
// 遍历数组
for (int i = 0; i < length; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
```
## 2.6 一维数组的内存分析
### 2.6.1 数组内存图
* 假设数组是如下的定义:
```c
int arr[] = {1,2,3,4,5};
```
* 那么,对应的内存结构,如下所示:
![](./assets/7.png)
> [!NOTE]
>
> * ① 数组名 `arr` 就是记录该数组的首地址,即 `arr[0]` 的地址。
> * ② 数组中的各个元素是连续分布的,假设 `arr[0]` 的地址是 `0xdea7bff880`,则 `arr[1] 的地址 = arr[0] 的地址 + int 字节数4 = 0xdea7bff880 + 4 = 0xdea7bff884` ,依次类推...
* 在 C 语言中,我们可以通过 `&arr``&arr[0]` 等形式获取数组或数组元素的地址,即:
```c
#include <stdio.h>
int main() {
// 定义数组
int arr[10];
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 给数组的每个元素赋值
for (int i = 0; i < length; i++) {
arr[i] = i;
}
printf("数组的地址是 = %p\n", arr);
// 遍历数组
for (int i = 0; i < length; i++) {
printf("数组元素 %d 的地址是 = %p\n", arr[i], &arr[i]);
}
return 0;
}
```
### 2.6.2 数组的注意事项
* `C 语言规定,数组一旦声明,数组名指向的地址将不可更改`。因为在声明数组的时候,编译器会自动会数组分配内存地址,这个地址和数组名是绑定的,不可更改。
> [!WARNING]
>
> 如果之后试图更改数组名对应的地址,编译器就会报错。
* 示例:错误演示
```c
int num[5]; // 声明数组
// 使用大括号重新赋值是不允许的,必须在数组声明的时候赋值,否则编译将会报错
num = {1,2,3,4,5} ; // 报错
```
* 示例:错误演示
```c
int num[] = {1,2,3,4,5};
// 使用大括号重新赋值是不允许的,必须在数组声明的时候赋值,否则编译将会报错
num = {2,3,4,5,6}; // 报错
```
* 示例:错误演示
```c
int num[5];
num = NULL; // 报错,需要和 Java 区别一下,在 C 中不可以
```
* 示例:错误演示
```c
int a[] = {1,2,3,4,5}
int b[5] = a ; // 报错,需要和 Java 区别一下,在 C 中不可以
```
## 2.7 数组应用案例
### 2.7.1 应用示例
* 需求:计算数组中所有元素的和以及平均数。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 15, 36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 变量保存总和
int sum = 0;
// 遍历数组
for (int i = 0; i < length; i++) {
sum += arr[i];
}
double avg = (double)sum / length;
printf("数组的和为:%d\n", sum); // 数组的和为375
printf("数组的平均值为:%.2lf\n", avg); //数组的平均值为37.50
return 0;
}
```
### 2.7.2 应用示例
* 需求:计算数组的最值(最大值和最小值)。
> [!NOTE]
>
> 思路:
>
> * ① 假设数组中的第一个元素是最大值或最小值,并使用变量 max 或 min 保存。
> * ② 遍历数组中的每个元素:
> * 如果有元素比最大值还要大,就让变量 max 保存最大值。
> * 如果有元素比最小值还要小,就让变量 min 保存最小值。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 定义最大值
int max = arr[0];
// 定义最小值
int min = arr[0];
// 遍历数组
for (int i = 0; i < length; i++) {
if (arr[i] >= max) {
max = arr[i];
}
if (arr[i] <= min) {
min = arr[i];
}
}
printf("数组的最大值为:%d\n", max); // 数组的最大值为108
printf("数组的最小值为:%d\n", min); // 数组的最小值为:-36
return 0;
}
```
### 2.7.3 应用示例
* 需求:统计数组中某个元素出现的次数,要求:使用无限循环,如果输入的数字是 0 ,就退出。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 2, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 遍历数组
printf("当前数组中的元素是:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 无限循环
while (true) {
// 统计的数字
int num;
// 统计数字出现的次数
int count = 0;
// 输入数字
printf("请输入要统计的数字:");
scanf("%d", &num);
// 0 作为结束条件
if (num == 0) {
break;
}
// 遍历数组,并计数
for (int i = 0; i < length; i++) {
if (arr[i] == num) {
count++;
}
}
printf("您输入的数字 %d 在数组中出现了 %d 次\n", num, count);
}
return 0;
}
```
### 2.7.4 应用示例
* 需求:将数组 a 中的全部元素复制到数组 b 中。
* 示例:
```c
#include <stdio.h>
#define SIZE 10
int main() {
// 定义数组并初始化
int a[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
int b[SIZE];
// 复制数组
for (int i = 0; i < SIZE; i++) {
b[i] = a[i];
}
// 打印数组 b 中的全部元素
for (int i = 0; i < SIZE; i++) {
printf("%d ", b[i]);
}
return 0;
}
```
### 2.7.5 应用示例
* 需求:数组对称位置的元素互换。
> [!NOTE]
>
> 思路:假设数组一共有 10 个元素,那么:
>
> * a[0] 和 a[9] 互换。
> * a[1] 和 a[8] 互换。
> * ...
>
> 规律就是 `a[i] <--互换--> arr[arr.length -1 -i]`
* 示例:
```c
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t SIZE = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 交换数组
for (int i = 0; i < SIZE / 2; i++) {
int temp = arr[i];
arr[i] = arr[SIZE - 1 - i];
arr[SIZE - 1 - i] = temp;
}
// 打印交换后的数组
printf("交换后数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
```
* 示例:
```c
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t SIZE = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 交换数组
for (int i = 0, j = SIZE - 1 - i; i < SIZE / 2; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 打印交换后的数组
printf("交换后数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
```
### 2.7.6 应用示例
* 需求:将数组中的最大值移动到数组的最末尾。
> [!NOTE]
>
> 思路:从数组的下标 `0` 开始依次遍历到 `length - 1` ,如果 `i` 下标当前的值比 `i+1` 下标的值大,则交换;否则,就不交换。
* 示例:
```c
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, -24, 15, -36, 67, 891, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 移动最大值到数组的最后一个位置
for (int i = 0; i < length - 1; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
// 打印移动之后的数组
printf("移动之后的数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
```
### 2.7.7 应用示例
* 需求:实现冒泡排序,即将数组的元素从小到大排列。
> [!NOTE]
>
> 思路:一层循环,能实现最大值移动到数组的最后;那么,二层循环(控制内部循环数组的长度)就能实现将数组的元素从小到大排序。
* 示例:
```c
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, -24, 15, -36, 67, 891, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\n");
for (int j = 0; j < length - 1; j++) {
for (int i = 0; i < length - 1 - j; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
// 打印移动之后的数组
printf("移动之后的数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
```
# 第三章:多维数组(⭐)
## 3.1 概述
### 3.1.1 引入
* 我们在数学、物理和计算机科学等学科中学习过`一维坐标`、`二维坐标`以及`三维坐标`。
* 其中,`一维坐标`通常用于描述在线段或直线上的点的位置,主要应用有:
* **数轴**:一维坐标可以用来表示数轴上的数值位置,这在基础数学和初等代数中非常常见。
![](./assets/8.png)
* **时间轴**:时间可以看作是一维的,它可以用一维坐标表示,例如:秒、分钟、小时等。
![](./assets/9.png)
* **统计数据**:一维坐标常用于表示单变量的数据集,如:测量身高、体重、温度等。
![](./assets/10.jpg)
* 其中,`二维坐标`用于描述平面上的点的位置。主要应用包括:
* **几何学**:在几何学中,二维坐标用于表示平面图形的顶点、边和面积等。
![](./assets/11.png)
* **地图和导航**:地理坐标系统(经纬度)使用二维坐标来表示地球表面的任意位置。
![image-20240724112326592](./assets/12.png)
* **图形设计和计算机图形学**:二维坐标在绘制图形、设计图案和用户界面中非常重要。
![](./assets/13.png)
* **物理学**:二维运动和场,例如:在描述物体在平面上的运动轨迹时使用二维坐标。
![](./assets/14.jpg)
* 其中,三维坐标用于描述空间中点的位置。主要应用包括:
* **几何学**:三维坐标在空间几何中用于表示立体图形的顶点、边、面和体积。
![](./assets/15.png)
* **计算机图形学**:三维建模和动画需要使用三维坐标来创建和操控虚拟对象。
![](./assets/16.png)
* **工程和建筑设计**:在设计建筑物、机械部件和其他工程项目时,使用三维坐标来精确定位和规划。
![](./assets/17.png)
* **物理学**:三维空间中的力、运动和场,例如:描述物体在空间中的位置和运动轨迹。
![](./assets/18.png)
* 总而言之,一维、二维和三维坐标系统在不同的领域中各有其重要的应用,从基础数学到高级科学和工程技术,它们帮助我们更好地理解和描述世界的结构和行为。
### 3.1.2 多维数组
* 在 C 语言中,多维数组就是数组嵌套,即:在数组中包含数组,数组中的每一个元素还是一个数组类型,如下所示:
![](./assets/19.png)
> [!NOTE]
>
> * ① 如果数组中嵌套的每一个元素是一个常量值,那么该数组就是一维数组。
> * ② 如果数组中嵌套的每一个元素是一个一维数组,那么该数组就是二维数组。
> * ③ 如果数组中前台的每一个元素是一个二维数组,那么该数组就是三维数组.
> * ④ 依次类推...
* 一维数组和多维数组的理解:
* 从内存角度看:一维数组或多维数组都是占用的一整块连续的内存空间。
* 从数据操作角度看:
* 一维数组可以直接通过`下标`访问到数组中的某个元素0、1、...
* 二维数组要想访问某个元素,先要获取某个一维数组,然后在一维数组中获取对应的数据。
> [!NOTE]
>
> * ① C 语言中的一维数组或多维数组都是占用的一整块连续的内存空间其它编程语言可不是这样的Java 等。
> * ② 在实际开发中,最为常用的就是二维数组或三维数组了,以二维数组居多!!!
## 3.2 二维数组的定义
### 3.2.1 动态初始化
* 语法:
```c
数据类型 数组名[几个⼀维数组元素][每个⼀维数组中有几个具体的数据元素];
```
> [!NOTE]
>
> * ① 二维数组在实际开发中,最为常见的应用场景就是表格或矩阵了。
> * ② 几个一维数组元素 = 行数。
> * ③ 每个⼀维数组中有几个具体的数据元素 = 列数。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义二维数组并初始化
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
// 输出二维数组中的元素
printf("%d ", arr[0][0]);
printf("%d ", arr[0][1]);
printf("%d ", arr[0][2]);
printf("%d \n", arr[0][3]);
printf("%d ", arr[1][0]);
printf("%d ", arr[1][1]);
printf("%d ", arr[1][2]);
printf("%d \n", arr[1][3]);
printf("%d ", arr[2][0]);
printf("%d ", arr[2][1]);
printf("%d ", arr[2][2]);
printf("%d ", arr[2][3]);
return 0;
}
```
### 3.2.2 静态初始化 1
* 语法:
```c
数据类型 数组名[行数][列数] = {{元素1,元素2,...},{元素3,...},...}
```
> [!NOTE]
>
> * ① 行数 = 几个一维数组元素。
> * ② 列数 = 每个⼀维数组中有几个具体的数据元素。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义二维数组并初始化
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
// 输出二维数组中的元素
printf("%d ", arr[0][0]);
printf("%d ", arr[0][1]);
printf("%d ", arr[0][2]);
printf("%d \n", arr[0][3]);
printf("%d ", arr[1][0]);
printf("%d ", arr[1][1]);
printf("%d ", arr[1][2]);
printf("%d \n", arr[1][3]);
printf("%d ", arr[2][0]);
printf("%d ", arr[2][1]);
printf("%d ", arr[2][2]);
printf("%d ", arr[2][3]);
return 0;
}
```
### 3.2.3 静态初始化 2
* 语法:
```c
数据类型 数组名[][列数] = {{元素1,元素2,...},{元素3,...},...}
```
> [!NOTE]
>
> * ① 列数 = 每个⼀维数组中有几个具体的数据元素。
> * ② 可以不指定行数,必须指定列数,编译器会根据元素的个数和列的个数,自动推断出行数!!!
* 示例:
```c
#include <stdio.h>
int main() {
// 定义二维数组
int arr[][4] = {{1, 2, 3, 4}, {5, 6}, {9, 10, 11, 12}};
// 输出二维数组中的元素
printf("%d ", arr[0][0]);
printf("%d ", arr[0][1]);
printf("%d ", arr[0][2]);
printf("%d \n", arr[0][3]);
printf("%d ", arr[1][0]);
printf("%d \n", arr[1][1]);
printf("%d ", arr[2][0]);
printf("%d ", arr[2][1]);
printf("%d ", arr[2][2]);
printf("%d ", arr[2][3]);
return 0;
}
```
## 3.3 二维数组的理解
* 如果二维数组是这么定义的,即:
```c
int arr[3][4];
```
* 那么,这个二维数组 `arr` 可以看做是 `3` 个一维数组组成,它们分别是 `arr[0]`、`arr[1]`、`arr[2]`。这 `3` 个一维数组都各有 4 个元素,如:一维数组 `arr[0]` 中的元素是 `arr[0][0]`、`arr[0][1]`、`arr[0][2]`、`arr[0][3]`,即:
![](./assets/20.png)
## 3.4 二维数组的遍历
* 访问二维数组的元素,需要使用两个下标(索引),一个用于访问行(第一维),另一个用于访问列(第二维),我们通常称为行下标(行索引)或列下标(列索引)。
* 所以,遍历二维数组,需要使用双层循环结构。
> [!NOTE]
>
> 如果一个二维数组是这么定义的,即:`int arr[3][4]`,那么:
>
> * `行的长度 = sizeof(arr) / sizeof(arr[0])` ,因为 `arr` 是二维数组的`总`的内存空间;而 `arr[0]` 、`arr[1]`、`arr[2]` 是二维数组中一维数组的内存空间 。
> * `列的长度 = sizeof(arr[0]) / sizeof(arr[0][0])`,因为`arr[0]` 、`arr[1]`、`arr[2]` 是二维数组中一维数组的内存空间 ,而 `arr[0][0]`、`arr[0][1]`、... 是一维数组中元素的内存空间。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义二维数组
int arr[][4] = {{1, 2, 3, 4}, {5, 6}, {9, 10, 11, 12}};
// 获取行列数
int row = sizeof(arr) / sizeof(arr[0]);
int col = sizeof(arr[0]) / sizeof(arr[0][0]);
// 打印二维数组元素
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
```
## 3.5 二维数组的内存分析
* 用`矩阵形式`3 行 4 列形式)表示二维数组,是`逻辑`上的概念,能形象地表示出行列关系。而在`内存`中,各元素是连续存放的,不是二维的,是`线性`的。
* C 语言中,二维数组中元素排列的顺序是`按行存放`的。即:先顺序存放第一行的元素,再存放第二行的元素。例如:数组`a[3][4] `在内存中的存放,如下所示:
![](./assets/21.png)
## 3.6 二维数组的应用案例
* 需求:现在有三个班,每个班五名同学,用二维数组保存他们的成绩,并求出每个班级平均分、以及所有班级平均分,数据要求从控制台输入。
* 示例:
```c
#include <stdio.h>
int main() {
// 定义二维数组,用于保存成绩
double arr[3][5];
// 获取二维数组的行数和列数
int row = sizeof(arr) / sizeof(arr[0]);
int col = sizeof(arr[0]) / sizeof(arr[0][0]);
// 从控制台输入成绩
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("请输入第%d个班级的第%d个学生的成绩", i + 1, j + 1);
scanf("%lf", &arr[i][j]);
}
}
// 总分
double totalSum = 0;
// 遍历数组,求总分和各个班级的平均分
for (int i = 0; i < row; i++) {
double sum = 0;
for (int j = 0; j < col; j++) {
totalSum += arr[i][j];
sum += arr[i][j];
}
printf("第%d个班级的总分为%.2lf\n", i + 1, sum);
printf("第%d个班级的平均分为%.2lf\n", i + 1, sum / col);
}
printf("所有班级的总分为:%.2lf\n", totalSum);
printf("所有班级的平均分为:%.2lf\n", totalSum / (row * col));
return 0;
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

View File

@ -0,0 +1,510 @@
> * `指针`是 C 语言中`最重要`的概念之一,也是`最难以理解`的概念之一。
> * `指针`是 C 语言的`精髓`,要想掌握 C 语言就需要深入地了解指针。
# 第一章:颇具争议的指针
## 1.1 概述
* 目前而言,操作系统几乎都是通过 C 语言来编写和维护的;而 C 语言提供了指针的用法,其能直接操作内存地址,是个非常`强大`和`灵活`的工具;但是,需要开发者`小心谨慎的使用`,以确保程序的稳定性和安全性。
> [!NOTE]
>
> 之所以指针在 C 语言中颇具争议,是因为一方面其功能强大,直接操作内存地址;另一方面,又很危险,不正确的使用指针的方式,非常容易导致程序崩溃。
* 如果没有能很好的使用指针,就会带来一系列的问题,如:
* ① **空指针引用Null Pointer Dereference**当一个指针没有正确初始化或者被赋予了空NULL值时如果程序尝试访问该指针所指向的内存会导致运行时错误甚至导致程序崩溃。
* ② **野指针Dangling Pointers**:指针指向的内存地址曾经分配给某个变量或对象,但后来该变量或对象被释放或者移动,导致指针仍指向已经无效的内存位置。对野指针进行操作可能会导致未定义的行为或程序崩溃。
* ③ **指针算术错误**:在进行指针运算时,如果没有正确管理指针的偏移量或者超出了数组的边界,可能会导致指针指向错误的内存位置,从而影响程序的正确性和安全性。
* ④ **内存泄漏**:如果动态分配的内存通过指针分配,但在不再需要时没有正确释放,会导致内存泄漏,长时间运行的程序可能会耗尽系统资源。
* 为了减少指针带来的风险,开发人员可以采取以下的措施:
* ① **良好的编程实践**:确保指针的初始化和使用是安全的,避免空指针引用和野指针问题。
* ② **边界检查**:在进行指针运算时,始终确保不会超出数组或内存分配的边界。
* ③ **使用指针和引用的适当性**:在可能的情况下,可以考虑使用更安全的语言特性,如:引用(在 C++ 等编程语言中)或者更高级别的数据结构来代替裸指针,从而减少指针使用时的潜在风险。
> [!IMPORTANT]
>
> * ① 既然指针很危险那么通过一系列的手段将指针包装或屏蔽以达到程序安全的目的这是现代化的高级编程语言解决的思路Java、Go、Rust 等)。
> * ② 之所以指针还需要学习是因为在嵌入式等领域其机器的资源CPU、内存等非常有限而现代化的高级编程语言虽然安全但是需要的系统资源也庞大。
> * ③ 我们知道编译型的程序不管编译过程如何复杂至少需要两步编译和运行。通常我们也将这两步称为编译期和运行期。C 语言中的指针之所以危险就在于程序要在运行的时候才会发现问题(后知后觉);而现代化的高级编程语言中的编译器在程序编译的时候就会发现问题(提前发现问题)。
> * ④ C 语言的编译器之所以这么设计的原因,就在于当时的内存和 CPU 是非常有限PDP-7 早期小型计算机CPU18 bit 的电子管逻辑内存4kb 和昂贵72,000 $),如果加入安全限制的功能,会远远超过整个系统的资源。
## 1.2 现代化高级编程语言是如何解决指针危险的?
* `C++`采用了如下的策略和机制,来解决指针危险操作的:
* ① **智能指针:** C++ 引入了智能指针(如`std::shared_ptr`、`std::unique_ptr`),这些指针提供了自动资源管理和所有权的语义。`std::unique_ptr`确保只有一个指针可以访问给定的资源,从而避免了传统指针的悬空引用和内存泄漏问题。`std::shared_ptr`允许多个指针共享一个资源,并在所有引用释放后自动释放。
* ② **引用:** C++ 中的引用(如:`&`符号)提供了更安全的间接访问方法,与指针相比,引用不能重新绑定到不同的对象,从而减少了意外的指针错误。
* `Go`采用了如下的策略和机制,来解决指针危险操作的:
* ① **内存管理和垃圾回收:** Go 语言通过自动垃圾回收器管理内存减少了手动内存管理所带来的指针操作错误。Go 的垃圾回收器定期扫描并释放不再使用的内存,避免了内存泄漏和悬空指针问题。
* ② **指针的安全性:** Go 语言的指针是受限的,不支持指针运算,从而减少了指针操作可能带来的风险。
* `Rust`采用了如下的策略和机制,来解决指针危险操作的:
* ① **所有权和借用:** Rust 引入了所有权和借用的概念,编译器在编译时静态分析所有权转移和引用的生命周期。这种机制避免了数据竞争和空指针解引用等运行时错误,使得在编译时就能够保证内存安全。
* ② **生命周期:** Rust 的生命周期系统确保引用的有效性和安全性,防止了悬空引用和指针乱用。
* `Java`采用了如下的策略和机制,来解决指针危险操作的:
* ① **引用类型和自动内存管理:** Java 中所有的对象引用都是通过引用来访问的而不是直接的指针。Java 的自动垃圾回收器负责管理内存,从而避免了手动内存管理可能导致的指针错误,如:内存泄漏和悬空指针。
* ② **强类型系统和异常处理:** Java 的强类型系统和异常处理机制减少了指针操作带来的风险空指针解引用异常NullPointerException。编译器在编译时能够捕获许多潜在的类型错误进一步增强了程序的安全性和可靠性。
> [!IMPORTANT]
>
> 总而言之,各种编程语言通过引入不同的策略和机制,如:智能指针、垃圾回收器、所有权和借用,以及强类型系统,有效地减少了指针操作所带来的各种安全性和可靠性问题,提升了程序的稳定性和开发效率。
# 第二章:回顾知识
## 2.1 变量
* 变量就是保存程序运行过程中临时产生的值,其语法如下:
```c
数据类型 变量名 = 值 ;
```
> [!IMPORTANT]
>
> 变量名(标识符)需要符合命名规则和命名规范!!!
>
> * 强制规范:
> - ① 只能由`小写`或`大写英文字母``0-9` 或 `_` 组成。
> - ② 不能以`数字`开头。
> - ③ 不可以是`关键字`。
> - ④ 标识符具有`长度`限制,不同编译器和平台会有所不同,一般限制在 63 个字符内。
> - ⑤ 严格`区分大小写字母`Hello、hello 是不同的标识符。
> * 建议规范:
> - ① 为了提高阅读性使用有意义的单词见名知意sumnamemaxyear 等。
> - ② 使用下划线连接多个单词组成的标识符max_classes_per_student 等。
> - ③ 多个单词组成的标识符,除了使用下划线连接,也可以使用小驼峰命名法,除第一个单词外,后续单词的首字母大写,如: studentId、student_name 等。
> - ④ 不要出现仅靠大小写区分不同的标识符name、Name 容易混淆。
> - ⑤ 系统内部使用了一些下划线开头的标识符C99 标准添加的类型 `_Bool`,为防止冲突,建议开发者尽量避免使用下划线开头的标识符。
* `变量名`的`作用`,如下所示:
* ① 当我们`编写`代码的时候,使用`变量名`来`关联`某块内存的`地址`。
* ② 当 CPU `执行`的时候,会将变量名`替换`为具体的地址,再进行具体的操作。
## 2.2 普通变量和指针变量的区别
* 根据`变量`中`存储`的`值`的`不同`,我们可以将`变量`分为两类:
- `普通变量`:变量所对应的内存中存储的是`普通值`。
- `指针变量`:变量所对应的内存中存储的是`另一个变量的地址`。
* 如下图所示:
![img](./assets/1.png)
* 普通变量和指针变量的相同点,如下所示:
* ① 普通变量有内存空间,指针变量也有内存空间。
* ② 普通变量有内存地址,指针变量也有内存地址。
* ③ 普通变量所对应的内存空间中有值,指针变量所对应的内存空间中也有值。
* 普通变量和指针变量的不同点:
- ① `普通变量`所对应的内存空间`存储`的是`普通的值`,如:整数、小数、字符等;`指针变量`所对应的内存空间`存储`的是另外一个变量的`地址`。
- ② `普通变量有普通变量的运算方式`,而`指针变量有指针变量的运算方式`(后续讲解)。
## 2.3 运算符
### 2.3.1 概述
* 运算符是一种特殊的符号,用于数据的运算、赋值和比较等。
* `表达式`指的是一组运算数、运算符的组合,表达式`一定具有值`,一个变量或一个常量可以是表达式,变量、常量和运算符也可以组成表达式,如:
![img](./assets/2.png)
- `操作数`指的是`参与运算`的`值`或者`对象`,如:
![](./assets/3.png)
* 根据`操作数`的`个数`,可以将运算符分为:
* 一元运算符(一目运算符)。
* 二元运算符(二目运算符)。
* 三元运算符(三目运算符)。
* 根据`功能`,可以将运算符分为:
* 算术运算符。
* 关系运算符(比较运算符)。
* 逻辑运算符。
* 赋值运算符。
* 逻辑运算符。
* 位运算符。
* 三元运算符。
> [!NOTE]
>
> 掌握一个运算符,需要关注以下几个方面:
>
> - ① 运算符的含义。
> - ② 运算符操作数的个数。
> - ③ 运算符所组成的表达式。
> - ④ 运算符有无副作用,即:运算后是否会修改操作数的值。
> [!IMPORTANT]
>
> 普通变量支持上述的所有运算符;而指针变量并非支持上述的所有运算符,且支持运算符的含义和普通变量相差较大!!!
### 2.3.2 运算符的优先级
* C 语言中运算符的优先级,如下所示:
| **优先级** | **运算符** | **名称或含义** | **结合方向** |
| ---------- | ---------- | ---------------- | ------------- |
| **1** | `[]` | 数组下标 | ➡️(从左到右) |
| | `()` | 圆括号 | |
| | `.` | 成员选择(对象) | |
| | `->` | 成员选择(指针) | |
| **2** | `-` | 负号运算符 | ⬅️(从右到左) |
| | `(类型)` | 强制类型转换 | |
| | `++` | 自增运算符 | |
| | `--` | 自减运算符 | |
| | `*` | 取值运算符 | |
| | `&` | 取地址运算符 | |
| | `!` | 逻辑非运算符 | |
| | `~` | 按位取反运算符 | |
| | `sizeof` | 长度运算符 | |
| **3** | `/` | 除 | ➡️(从左到右) |
| | `*` | 乘 | |
| | `%` | 余数(取模) | |
| **4** | `+` | 加 | ➡️(从左到右) |
| | `-` | 减 | |
| **5** | `<<` | 左移 | ➡️(从左到右) |
| | `>>` | 右移 | |
| **6** | `>` | 大于 | ➡️(从左到右) |
| | `>=` | 大于等于 | |
| | `<` | 小于 | |
| | `<=` | 小于等于 | |
| **7** | `==` | 等于 | ➡️(从左到右) |
| | `!=` | 不等于 | |
| **8** | `&` | 按位与 | ➡️(从左到右) |
| **9** | `^` | 按位异或 | ➡️(从左到右) |
| **10** | `\|` | 按位或 | ➡️(从左到右) |
| **11** | `&&` | 逻辑与 | ➡️(从左到右) |
| **12** | `\|\|` | 逻辑或 | ➡️(从左到右) |
| **13** | `?:` | 条件运算符 | ⬅️(从右到左) |
| **14** | `=` | 赋值运算符 | ⬅️(从右到左) |
| | `/=` | 除后赋值 | |
| | `*=` | 乘后赋值 | |
| | `%=` | 取模后赋值 | |
| | `+=` | 加后赋值 | |
| | `-=` | 减后赋值 | |
| | `<<=` | 左移后赋值 | |
| | `>>=` | 右移后赋值 | |
| | `&=` | 按位与后赋值 | |
| | `^=` | 按位异或后赋值 | |
| | `\|=` | 按位或后赋值 | |
| **15** | `,` | 逗号运算符 | ➡️(从左到右) |
> [!WARNING]
>
> * ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量`使用小括号来控制`表达式的执行顺序。
> * ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它`分成几步`来完成。
> * ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。
> [!IMPORTANT]
>
> * ① 取值运算符 `*` 和取地址运算符 `&` 的优先级相同,并且运算方向都是从右向左!!!
> * ② 逗号运算符 `,` 的优先级最低,并且运算方向是从左向右!!!
# 第三章:环境切换为 WSL
## 3.1 概述
* 前文说过C 语言中的指针是否使用是个颇具争议的话题现代化的高级编程语言通过各种策略和机制在编译期就能解决指针危险的问题。但是遗憾的是C 语言的指针很大程度上,在运行期才会暴露问题。
* 幸运的是,我们可以使用 `Valgrind` 项目来进行`内存泄露检测`和`性能分析`,而 Valgrind 只支持 Linux 。
> [!NOTE]
>
> win 11 中的 WSL2 就是个 Linux 环境,我们可以在上面跑各种 Linux 工具这样我们就不需要再安装虚拟机软件了VMware Workstation它会完整的模拟一个硬件系统并在上面跑各种 Linux ,实在是太笨重了)。
## 3.2 使用步骤
* 在 WSL2 上安装 Valgrind
```shell
dnf -y upgrade && dnf -y install valgrind # AlmaLinux
```
```shell
apt -y update && apt -y upgrade && apt -y install valgrind # Ubuntu
```
![](./assets/4.gif)
* 查看 valgrind 可执行文件的安装位置:
```shell
which valgrind
```
![](./assets/5.gif)
* CLion 中将工具链设置为 WSL2
![](./assets/6.gif)
* CLion 中配置 valgrind 的路径:
![](./assets/7.png)
* 查看 WSL2 中 cmake 的版本:
```shell
cmake --version
```
![](./assets/8.png)
* 修改项目中 CMakeLists.txt 中 cmake 的版本:
```{1} txt
cmake_minimum_required(VERSION 3.26.5) # 3.26.5
# 项目名称和版本号
project(c-study VERSION 1.0 LANGUAGES C)
# 设置 C 标准
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED True)
# 辅助函数,用于递归查找所有源文件
function(collect_sources result dir)
file(GLOB_RECURSE new_sources "${dir}/*.c")
set(${result} ${${result}} ${new_sources} PARENT_SCOPE)
endfunction()
# 查找顶层 include 目录(如果存在)
if (EXISTS "${CMAKE_SOURCE_DIR}/include")
include_directories(${CMAKE_SOURCE_DIR}/include)
endif ()
# 查找所有源文件
set(SOURCES)
collect_sources(SOURCES ${CMAKE_SOURCE_DIR})
# 用于存储已经处理过的可执行文件名,防止重复
set(EXECUTABLE_NAMES)
# 创建可执行文件
foreach (SOURCE ${SOURCES})
# 获取文件的相对路径
file(RELATIVE_PATH REL_PATH ${CMAKE_SOURCE_DIR} ${SOURCE})
# 将路径中的斜杠替换为下划线,生成唯一的可执行文件名
string(REPLACE "/" "_" EXECUTABLE_NAME ${REL_PATH})
string(REPLACE "\\" "_" EXECUTABLE_NAME ${EXECUTABLE_NAME})
string(REPLACE "." "_" EXECUTABLE_NAME ${EXECUTABLE_NAME})
# 处理与 CMakeLists.txt 文件同名的问题
if (${EXECUTABLE_NAME} STREQUAL "CMakeLists_txt")
set(EXECUTABLE_NAME "${EXECUTABLE_NAME}_exec")
endif ()
# 检查是否已经创建过同名的可执行文件
if (NOT EXECUTABLE_NAME IN_LIST EXECUTABLE_NAMES)
list(APPEND EXECUTABLE_NAMES ${EXECUTABLE_NAME})
# 创建可执行文件
add_executable(${EXECUTABLE_NAME} ${SOURCE})
# 查找源文件所在的目录,并添加为包含目录(头文件可能在同一目录下)
get_filename_component(DIR ${SOURCE} DIRECTORY)
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${DIR})
# 检查并添加子目录中的 include 目录(如果存在)
if (EXISTS "${DIR}/include")
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${DIR}/include)
endif ()
# 检查并添加 module 目录中的所有 C 文件(如果存在)
if (EXISTS "${DIR}/module")
file(GLOB_RECURSE MODULE_SOURCES "${DIR}/module/*.c")
target_sources(${EXECUTABLE_NAME} PRIVATE ${MODULE_SOURCES})
endif ()
endif ()
endforeach ()
```
* 在 CLion 中正常运行代码:
![](./assets/9.gif)
* 在 CLion 中通过 valgrind 运行代码:
![](./assets/10.gif)
# 第四章:指针的理解和定义(⭐)
## 4.1 概述
*
## 4.2 普通变量和指针变量的区别
在 CLion 中使用 GDB 调试时,可以通过反编译代码来查看指针变量和普通变量的区别。下面是具体的步骤:
### 设置 GDB 调试器
1. 打开 CLion并加载你的项目。
2. 确保你使用的是带有 GDB 支持的工具链(如 GCC 工具链)。
3. 在 CLion 的设置中,确保调试器设置为 GDB。
### 编译你的代码
确保在编译你的代码时使用了调试信息生成选项(如 `-g`)。你可以在 CMakeLists.txt 文件中添加以下行:
```cmake
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
```
### 开始调试
1. 设置断点:在代码中你想要查看变量的地方设置一个断点。
2. 启动调试:点击调试按钮启动调试会话。
### 查看变量
当调试器在断点处暂停时,你可以在调试控制台中使用 GDB 命令来查看变量。以下是一些常用的 GDB 命令:
- `print variable_name`:打印变量的值。
- `info locals`:打印当前作用域中的所有局部变量。
- `whatis variable_name`:显示变量的类型。
### 区分指针变量和普通变量
指针变量和普通变量的主要区别在于它们的类型和存储的内容。指针变量存储的是地址,而普通变量存储的是实际的值。通过 GDB 命令可以很容易地看到这种区别。
#### 示例
假设有如下代码:
```cpp
#include <iostream>
int main() {
int a = 10;
int *p = &a;
std::cout << "a: " << a << ", p: " << p << std::endl;
return 0;
}
```
在 CLion 中设置断点并开始调试,程序将在 `std::cout` 行暂停。此时在调试控制台中输入以下命令:
- `print a`:输出变量 `a` 的值,应该是 `10`
- `print p`:输出指针变量 `p` 的值,即 `a` 的地址。
- `print *p`:输出指针 `p` 指向的值,即 `10`
通过这些命令,你可以看到指针变量 `p` 实际上存储的是一个地址,而普通变量 `a` 存储的是一个整数值。
#### 使用反汇编
在某些情况下,你可能需要查看反汇编代码来更深入地理解变量的存储方式。使用以下命令可以查看当前函数的反汇编代码:
- `disassemble`:反汇编当前函数的代码。
- `x/4wx &a`:查看变量 `a` 的内存内容。
### 总结
在 CLion 中使用 GDB 调试时,通过查看变量值和反汇编代码,可以清楚地区分指针变量和普通变量。指针变量存储地址,而普通变量存储实际的值,通过适当的 GDB 命令可以轻松辨别两者的区别。
# 第五章:指针的运算(⭐)
## 5.1 概述
## 5.2 总结
* 在 C 语言中,`普通变量`是直接存储`数据`的`变量`。对于普通变量,支持的操作包括:
* ① **赋值操作**:给变量赋值,如:`int a = 5`。
* ② **算术运算**:可以对数值类型的普通变量进行加、减、乘、除等运算,如:`a + b`、`a - b`、`a * b`、`a / b`
* ③ **关系运算**:可以进行比较运算(大于、小于、等于等),如: `a > b`、`a == b`。
* ④ **逻辑运算**:对布尔类型的值进行与、或、非运算,如: `a && b`、`a || b`、`!a`。
* ⑤ **位运算**:对整数类型的值进行位操作(与、或、异或、取反、左移、右移等),如: `a & b`、`a | b`、`a ^ b`、`~a`、`a << 2`、`a >> 2`。
* ⑥ **自增自减运算**`a++`、`--a` 等。
* 在 C 语言中,`指针变量`存储的是`另一个变量`的`地址`。对于指针变量,支持的操作包括:
* ① **赋值操作**:可以将一个地址赋值给指针,如: `int *p = &a;`
* ② **解引用操作**:通过指针访问它指向的变量,如: `*p = 10;` 修改指向变量的值。
* ③ **指针运算**
* **指针和整数值的加减运算**:指针可以进行整数的加减运算,用于访问数组或结构体成员,如: `p + 1`
* **指针的自增和自减运算**:指的是内存地址的向前或向后移动,如:`p++`、`p--`。
* **指针间的相减运算**:两个指向同一数组的指针相减可以得到它们之间的元素个数,如: `ptr1 - ptr2`
* **指针间的比较运算**:可以比较两个指针的大小,比较的是各自内存地址的大小,如: `p1 == p2`、`p1 != p2`。
* ④ **数组访问**:指针可以用于访问数组中的元素,通过 `*(p + i)` 访问第 `i` 个元素。
* ⑤ **指向指针的指针**:可以声明指向指针的指针,即多级指针,如:`int **pp = &p;`。
> [!WARNING]
>
> 在使用指针时,务必小心避免野指针和内存泄漏等问题。
在C语言中同类指针相减的结果是一个整数它表示两个指针之间相隔多少个指向的对象单位而不是它们在内存中的字节偏移量。这种对象单位是指针所指向的具体类型的大小。
举个例子来说,如果你有两个指向整数数组元素的指针 `p``q`,那么 `p - q` 的结果将是 `p` 指向的数组元素的索引与 `q` 指向的数组元素索引之间的差值。这个差值代表了在数组中相隔多少个整数元素,而不是它们在内存中的字节偏移量。
这种设计的优势在于,它使得指针运算更加直观和便于理解,特别是在处理数组和其他连续存储的数据结构时。因为指针运算结果的单位是根据指针所指向的具体类型来计算的,这样可以确保不同平台上的程序行为是一致的,不会受到底层硬件架构或者字节对齐规则的影响。
在C语言中数组名和指针有很多相似之处但数组名并不是指针变量。数组名实际是一个常量它指向数组的第一个元素的地址。为了证明这一点可以通过以下几个方面来说明
1. **数组名表示数组首地址**
数组名可以作为一个指针使用,数组名本身表示的是数组首地址。
```c
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // 这句话是合法的ptr现在指向arr[0]
printf("%p\n", arr); // 打印数组名,会打印数组首地址
printf("%p\n", &arr[0]); // 打印第一个元素的地址
```
2. **数组名是常量指针**
数组名是一个常量指针,不能改变它指向的位置,而指针变量可以改变它指向的位置。
```c
int arr[5];
int *ptr = arr; // 合法ptr指向arr[0]
ptr++; // 合法ptr现在指向arr[1]
// arr++; // 非法,编译错误,因为数组名是常量,不能改变
```
3. **sizeof运算符的结果不同**
使用`sizeof`运算符对数组名和指针变量会得到不同的结果,数组名会返回整个数组的大小,而指针变量会返回指针本身的大小。
```c
int arr[5];
int *ptr = arr;
printf("sizeof(arr) = %lu\n", sizeof(arr)); // 返回数组的大小5 * sizeof(int)
printf("sizeof(ptr) = %lu\n", sizeof(ptr)); // 返回指针的大小通常是4或8字节
```
4. **地址运算符的结果不同**
使用地址运算符`&`对数组名和指针变量会得到不同的结果,对数组名使用`&`会返回数组的地址,而对指针变量使用`&`会返回指针变量本身的地址。
```c
int arr[5];
int *ptr = arr;
printf("Address of array: %p\n", &arr); // 返回整个数组的地址
printf("Address of pointer: %p\n", &ptr); // 返回指针变量ptr的地址
```
综上所述,通过这些示例和解释,可以看出数组名虽然在某些场合下可以像指针一样使用,但它并不是一个真正的指针变量,而是一个常量,表示数组的首地址。

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,401 @@
# 第一章Linux
## 1.1 Linux 概述
* Linux 是一种开源的操作系统最初由芬兰的林纳斯·托瓦兹Linus Torvalds开发。它基于 UNIX 操作系统并且具有高度的可定制性和灵活性。Linux 操作系统被广泛应用于`服务器`、嵌入式系统和个人计算机等领域。
* 它具有稳定性、安全性和可靠性并且支持多用户、多任务和多线程。Linux 拥有众多的发行版Ubuntu、Red Hat、Debian 等,每个发行版都有自己的特点和优势。
* 由于其开源性质Linux 操作系统受到了全球开发者的广泛支持和贡献,成为了计算机行业中的重要组成部分。
## 1.2 Linux 的发展史
* Linux 的发展历史可以分为以下几个阶段:
* ① 初始阶段1991 - 1994 年):林纳斯·托瓦兹在 1991 年发布了 Linux 内核的第一个版本并将其开源。在接下来的几年里Linux 逐渐吸引了一些开发者的关注和参与,开始逐步完善和扩展功能。
* ② 发展阶段1995 - 2000 年在这个阶段Linux 开始受到更多人的关注和认可。许多开发者和公司开始为 Linux 开发应用程序和驱动程序为其增加更多的功能和兼容性。同时一些发行版如Red Hat、Debian 等也开始出现,为用户提供了更方便的安装和使用方式。
* ③ 商业化阶段2001 - 至今):随着 Linux 的成熟和广泛应用,越来越多的公司开始将 Linux 作为服务器和嵌入式设备的操作系统。一些大型科技公司IBM、Oracle 等也开始投入大量资源支持 Linux 的发展。同时,一些商业化的 Linux 发行版SUSE、Ubuntu 等也崭露头角,为企业和个人用户提供了更专业的支持和服务。
* ④ 社区发展阶段Linux 的发展一直依赖于全球开发者社区的贡献和支持。Linux 社区不断壮大吸引了众多的开发者和爱好者参与其中。通过社区的力量Linux 不断更新迭代,推出了许多新的版本和功能。
* 总的来说Linux 的发展历程是一个由个人项目逐渐发展为全球开源社区支持的过程。它的成功得益于开源模式的优势,以及全球开发者的共同努力和贡献。
## 1.3 Linux 的组成(⭐)
* Linux 主要由以下几个组成部分构成:
* ① `Linux 内核`Linux 内核是整个操作系统的核心,负责管理硬件设备、内存管理、进程调度等核心功能。它是由林纳斯·托瓦兹及其他开发者编写和维护的。
* ② `Shell 解释器`Shell 解释器是用户与操作系统交互的接口,它接收用户输入的命令并将其解释执行。常见的 Shell 解释器有 Bash、Zsh 等,它们提供了命令行界面和脚本编程功能。
* ③ `外围的应用程序`:命令、应用程序、图形化界面……
* 其图示如下:
![image-20240115214505877](./assets/1.png)
* 上述的组成部分共同构成了一个完整的 Linux 操作系统,为用户提供了丰富的功能和灵活性。
## 1.4 Linux 发行版本(⭐)
* Linux `发行版本`就是:`Linux 内核` + `命令解释器` + `应用程序(桌面)`
* 主流的 Linux 发行版本如下:
| Linux 系统类别 | Linux 系统 | 备注 |
| -------------- | --------------------------------- | ------------------------------------------------------------ |
| Debian 系列 | `Debian` | 更新频率较低,较为稳定和安全,可以用于企业生产环境。 |
| | `Ubuntu` | 桌面美观,使用方便,开发使用。有桌面版和企业版本(服务器版本)。 |
| Redhat 系列 | RedHat Enterprise Linux`RHEL` | 红帽企业版本 |
| | CentOS | 基于 Red Hat Enterprise LinuxRHEL源代码构建的免费开源操作系统。它提供了企业级的稳定性和安全性广泛用于服务器环境。 |
| | Fedora | Fedora 是由 Red Hat 赞助的社区驱动的 Linux 发行版,注重最新的软件和技术。它提供了一个先进的桌面环境和开发者工具。 |
| | `Rocky Linux` | 用来替代 CentOS 系统的,也是基于 Red Hat Enterprise LinuxRHEL源代码构建的免费开源操作系统。 |
| | `Alma Linux` | 用来替代 CentOS 系统的,也是基于 Red Hat Enterprise LinuxRHEL源代码构建的免费开源操作系统。 |
| 其它系列 | SUSE、OpenSUSE | OpenSUSE 是一个用户友好且功能强大的 Linux 发行版,具有稳定性和灵活性。它提供了多种桌面环境和服务器选项。 |
* 当然,除了以上几个主流的 Linux 发行版还有许多其他的发行版Arch Linux、Gentoo、Mageia 等,它们各自有着不同的特点和适用场景。
* 选择适合自己需求的发行版是根据个人或组织的需求和偏好来决定的。
## 1.5 Linux 版本选择(⭐)
* 推荐选择 `LTS 版`或`稳定版`。
> [!WARNING]
>
> * LTS 是 `"Long-Term Support"` 的缩写意为长期支持。在软件开发领域LTS 通常用来描述某个版本或发行版的长期支持周期。
> * 对于 Linux 发行版或其他软件LTS 版本通常会提供更长时间的支持和维护,以确保稳定性和安全性。这意味着在 LTS 版本的支持周期内,开发者会持续提供安全补丁、错误修复和其他重要更新,以保持系统的稳定性和可靠性。
> * LTS 版本通常适用于企业和组织等需要长期稳定性和可靠性的环境。相比于非 LTS 版本LTS 版本的更新频率较低,更注重于提供长期支持和维护。
* 本次选择:
| 系统版本 | 说明 |
| --------------------------------------------------------- | ------------------------ |
| [Ubuntu](https://cn.ubuntu.com/) | LTS 18.04 、LTS 20.04 等 |
| [AlmaLinux](https://almalinux.org/zh-hans/get-almalinux/) | 9.1、9.2、9.3 等 |
# 第二章:工作和学习环境部署(⭐)
## 2.1 服务器
* `服务器`是一种专门用于提供服务的计算机系统。它通常具有更高的性能、可靠性和稳定性,以满足处理大量请求和提供持续服务的需求。
* `服务器`的主要功能是接收来自客户端的请求,并提供相应的服务或资源。这些服务可以包括:网站托管、数据库管理、文件存储、电子邮件、应用程序运行等。服务器通过网络与客户端进行通信,处理请求并返回相应的数据或结果。
* `服务器`通常采用高性能的硬件配置,如:多核处理器、大容量内存、高速存储设备等,以确保能够处理大量的并发请求。它们还通常具有冗余的设计,包括冗余电源、冗余网络连接和冗余存储等,以提高可靠性和可用性。
* `服务器`可以是物理服务器,即实际的硬件设备,也可以是虚拟服务器,即在物理服务器上通过虚拟化技术创建的虚拟机。无论是物理服务器还是虚拟服务器,它们都扮演着提供服务和资源的角色。
* 在企业和组织中,`服务器`通常由专门的 IT 团队进行管理和维护。他们负责服务器的配置、安全性、性能优化、备份和恢复等工作,以确保服务器的稳定运行和数据的安全性。
> [!TIP]
>
> 实际工作的时候,`Linux` 系统会运行在`服务器`上。
## 2.2 虚拟机概述
* 虚拟机Virtual Machine简称 VM是一种软件实现的`计算机系统`,它在物理计算机上`模拟`出一个`完整的计算环境`。虚拟机可以在同一台物理计算机上同时运行多个独立的操作系统和应用程序。
![2](./assets/2.png)
* 虚拟机的工作原理是通过`虚拟化技术`将物理计算机的硬件资源(如:处理器、内存、存储等)进行抽象和分配,为每个虚拟机提供一部分资源。每个虚拟机都被视为一个独立的计算机系统,可以运行自己的操作系统和应用程序。
* 虚拟机的优势在于它可以提供`隔离性`和`灵活性`。通过虚拟机,可以在同一台物理计算机上同时运行多个操作系统,实现资源的共享和最大化利用。同时,虚拟机还可以提供快速部署、快速备份和恢复等功能,方便管理和维护。
* 常见的虚拟机软件,包括:`VMware`、VirtualBox、KVM 等。它们提供了虚拟化平台和管理工具,使用户可以轻松创建、配置和管理虚拟机。虚拟机广泛应用于开发和测试环境、服务器虚拟化、云计算等领域。
> [!WARNING]
>
> `虚拟机软件`和`虚拟机`的概念不同:
>
> * ① `虚拟机软件`是用来模拟硬件一个`软件`VMware 等。
> * ② 而`虚拟机`是通过虚拟机软件模拟出来的`计算机硬件`,其实是文件的集合,相当于一台没有安装 Windows 操作系统的`裸机`。
> * ③ 在现实交谈的时候,我们有时候会模糊`虚拟机软件`和`虚拟机`的概念,甚至会使用`虚拟机`来代替`虚拟机软件`;此时,就需要根据`上下文环境(语境)`来判断到底说的是`虚拟机软件`还是`虚拟机`了。
## 2.3 安装虚拟机软件
### 2.3.1 前提条件
* 需要在 BIOS 中开启`虚拟化`功能。
![image-20240117085245337](./assets/3.png)
### 2.3.2 安装步骤
* ① 双击打开 VMware 安装程序 。
![双击打开VMware安装程序.png](./assets/4.png)
* ② 进行下一步安装:
![VMware进行下一步安装.png](./assets/5.png)
* ③ 同意许可协议,单击下一步:
![VMware同意许可协议单击下一步.png](./assets/6.png)
* ④ 根据需要决定是否需要更改软件的安装位置(建议放置于除 C 盘以外任意盘符下):
![VMware更改安装位置.png](./assets/7.png)
![VMware更改安装位置成功.png](./assets/8.png)
* ⑤ 更改成功后,单击确定,下一步继续安装:
![VMware更改成功后单击确定下一步继续安装.png](./assets/9.png)
* ⑥ 用户体验设置,如下图所示,单击下一步继续安装:
![VMware用户体验设置如下图所示单击下一步继续安装.png](./assets/10.png)
* ⑦ 快捷方式设置,单击下一步继续安装:
![VMware快捷方式设置单击下一步继续安装.png](./assets/11.png)
* ⑧ 单击安装按钮:
![VMware单击安装按钮.png](./assets/12.png)
* ⑨ VMware 输入许可证:
![VMware单击许可证.png](./assets/13.png)
![VMware输入许可证.png](./assets/14.png)
* ⑩ 安装结束后,单击完成按钮:
![VMware安装结束后单击完成按钮.png](./assets/15.png)
* ⑪ 检查虚拟机软件是否安装了虚拟网卡:
![查看VMware安装的虚拟网卡.png](./assets/16.png)
![查看VMware安装的虚拟网卡1.png](./assets/17.png)
![查看VMware安装的虚拟网卡2.png](./assets/18.png)
### 2.3.2 配置网络
* ① 打开 VMware 虚拟机软件:
![image-20240116202917529](./assets/19.png)
* ② 编辑 → 虚拟网络编辑器:
![image-20240116202955131](./assets/20.png)
* ③ Vmnet8 → 更改设置:
![image-20240116203207282](./assets/21.png)
* ④ 更改子网 IP 地址为 `192.168.10.0` ,其目的是为了将 IP 固定。
![image-20240116203357894](./assets/22.png)
* ⑤ DHCP 设置:
![image-20240116203529749](./assets/23.png)
![image-20240116203627959](./assets/24.png)
* ⑤ 通过 `cmd` ,输入 `ipconfig` 命令,查看是否配置成功:
![](./assets/25.gif)
## 2.4 创建虚拟机
### 2.4.1 概述
* 创建虚拟机,本质上就类似购买一台没有安装操作系统的`裸机`。
### 2.4.2 创建虚拟机
* ① 文件 → 新建虚拟机:
![image-20240117090352182](./assets/26.png)
* ② 选择`自定义`类型的配置:
![image-20240117090443216](./assets/27.png)
* ③ 虚拟机硬件兼容性:下一步即可。
![image-20240117090529266](./assets/28.png)
* ④ 选择`稍后安装操作系统`
![image-20240117090636337](./assets/29.png)
* ⑤ 选择虚拟机将安装的操作系统:
![image-20240117090805295](./assets/30.png)
* ⑥ 设置虚拟机的`名称`和`安装位置`
![image-20240117090944676](./assets/31.png)
> [!WARNING]
>
> 一个虚拟机一个安装目录(文件夹),防止引起文件的冲突。
* ⑦ 虚拟机中处理器的配置:下一步即可。
![image-20240117091051284](./assets/32.png)
* ⑧ 设置虚拟机的`内存`:至少 2048 MB以上。
![image-20240117091202131](./assets/33.png)
* ⑨ 设置虚拟机的`网络类型`:下一步即可。
![image-20240117091257738](./assets/34.png)
* ⑩ 设置 I/O 控制器类型:下一步即可。
![image-20240117091402913](./assets/35.png)
* ⑪ 选择磁盘类型:下一步即可。
![image-20240117091540264](./assets/36.png)
* ⑫ 选择磁盘:下一步即可。
![image-20240117091640870](./assets/37.png)
* ⑬ 选择磁盘容量:调整为 40 GB。
![image-20240117091832846](./assets/38.png)
* ⑭ 指定磁盘文件:下一步即可。
![image-20240117091907233](./assets/39.png)
* ⑮ 创建虚拟机完毕:
![image-20240117092013264](./assets/40.png)
* ⑯ 查看是否创建虚拟机成功:
![image-20240117092101810](./assets/41.png)
### 2.4.3 虚拟机归类(分类)
* 实际情况下,我们可能会创建很多`虚拟机`VMware 提供了`文件夹`的功能来管理虚拟机;其步骤如下所示:
* ① 鼠标右键 → 创建文件夹:
![image-20240117092324545](./assets/42.png)
* ② 修改文件夹的名称:
![image-20240117092600931](./assets/43.png)
![image-20240117092643086](./assets/44.png)
![image-20240117092720769](./assets/45.png)
* ③ 将刚才创建的虚拟机`拖`到该文件夹下:
![](./assets/46.gif)
### 2.4.4 设置 CD/DVD
* 以前,我们在一台裸机上安装操作系统的时候,需要通过 DVD 或 U 盘将操作系统的 ISO 镜像文件,安装到裸机上;
* 同理,在使用虚拟机软件的时候,也需要此类步骤;其步骤如下:
* ① 编辑虚拟机设置:
![image-20240117093143947](./assets/47.png)
* ② 选择硬盘上的 ISO 镜像文件:
![image-20240117093354461](./assets/48.png)
* ③ 查看是否配置成功:
![image-20240117093435976](./assets/49.png)
## 2.5 安装 Linux
* ① `开启此虚拟机`
![image-20240117093516070](./assets/50.png)
* ② `鼠标点击`进去之后,通过键盘上的`方向键`来选择:
![image-20240117093610205](./assets/51.png)
* 注意⚠️:键盘上的`方向键`在这里
![image-20240117093918602](./assets/52.png)
* ③ 设置操作系统的`语言`环境为`中文`
![image-20240117094530342](./assets/53.png)
* ④ 设置系统`安装目的地`
![](./assets/54.gif)
* ⑤ 设置`软件选择`:默认即可
![](./assets/55.gif)
* ⑥ 设置 root 的密码:`123456`即可
![](./assets/56.gif)
> [!WARNING]
>
> 学习阶段无所谓设置什么密码,但是生产环境,必须复杂并且经常更换!!!
* ⑦ 配置`网络和主机名`
![image-20240224223931266](./assets/57.png)
![image-20240224224038036](./assets/58.png)
![image-20240224224138061](./assets/59.png)
![image-20240224224209724](./assets/60.png)
![image-20240224224245924](./assets/61.png)
![image-20240224224344051](./assets/62.png)
* ⑧ 查看`配置网络和主机名`是否成功:
![image-20240224224420273](./assets/63.png)
* ⑨ 点击`开始安装`:漫长的等待……
![](./assets/64.gif)
* ⑩ 安装完成之后,会提示`重启系统`,那就重启吧:
![](./assets/65.gif)
## 2.6 远程连接 Linux
### 2.6.1 查看 Linux 的 IP 地址
* 通过 `ifconfig` 命令来查看 Linux 的 IP 地址:
```shell
ifconfig
```
![image-20240117101543732](./assets/66.png)
### 2.6.2 远程连接 Linux
* 可以通过 xshell 之类的远程连接工具来连接 Linux ,其步骤如下:
* ① 新建会话:
![image-20240117101749340](./assets/67.png)
* ② 输入 Linux 的 IP 地址:
![image-20240117101906927](./assets/68.png)
* ③ 输入用户名和密码:
![image-20240117102005340](./assets/69.png)
* ④ 接收和保存远程 Linux 的密钥:
![image-20240117102123845](./assets/70.png)
* ⑤ 查看是否登录成功:
![image-20240117102159684](./assets/71.png)

5
docs/notes/index.md Normal file
View File

@ -0,0 +1,5 @@
# c/c++ 学科
---
<iframe src="https://roadmap.sh/r/embed?id=6695c8262b17b182cbf4b520" width="115%" height="500px" frameBorder="0"></iframe>

BIN
docs/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

161
docs/public/logo.svg Normal file
View File

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 80.3 80.3" style="enable-background:new 0 0 80.3 80.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#EB6A5C;}
.st1{fill:#552F2F;}
.st2{fill:#55AB99;}
.st3{fill:#2F4555;}
.st4{fill:#FFFFFF;}
.st5{fill:#ED6B5A;}
.st6{fill:#0C2C48;}
.st7{fill:#F1CC4B;}
.st8{clip-path:url(#SVGID_2_);}
.st9{clip-path:url(#SVGID_2_);fill:#F6A09C;}
.st10{fill:#50646F;}
.st11{fill:#FCA886;}
.st12{fill:#EDAB7E;}
.st13{fill:#332319;}
.st14{fill:#E07E45;}
.st15{fill:#FF8F8F;}
.st16{fill:#A6D1D9;}
.st17{fill:#628185;}
.st18{fill:#BABABA;}
.st19{fill:#698391;}
.st20{opacity:0.41;fill:#FFFFFF;}
.st21{fill:#F6A09C;}
.st22{fill:#FFF3C9;}
.st23{fill:#2384AB;}
.st24{fill:#BABFC5;}
.st25{clip-path:url(#SVGID_4_);}
.st26{fill:#6EB9E0;}
.st27{fill:#F8A06D;}
.st28{fill:#A3B9C4;}
.st29{fill:#3B4A52;}
.st30{clip-path:url(#SVGID_6_);}
.st31{clip-path:url(#SVGID_8_);fill:#F6A09C;}
.st32{opacity:0.21;fill:#FFFFFF;}
.st33{clip-path:url(#SVGID_10_);fill:#F6A09C;}
.st34{clip-path:url(#SVGID_12_);}
.st35{fill:#FFD3B5;}
.st36{fill:#BFD9E6;}
.st37{fill:#798287;}
.st38{fill:#A4A8AD;}
.st39{fill:#FFD6BA;}
.st40{fill:none;stroke:#0C2C48;stroke-width:1.4;stroke-miterlimit:10;}
</style>
<g>
<g>
<circle class="st27" cx="40.2" cy="40.2" r="40.2"/>
</g>
<g>
<g>
<rect x="38.6" y="34.2" class="st6" width="1.3" height="25.8"/>
</g>
</g>
<g>
<ellipse class="st4" cx="23.1" cy="18" rx="10.3" ry="4.8"/>
</g>
<g>
<g>
<g>
<g>
<path class="st2" d="M46,51.5c0,0.4-0.4,0.8-0.8,0.8H33.4c-0.4,0-0.8-0.4-0.8-0.8v-9.9c0-0.4,0.4-0.8,0.8-0.8h11.9
c0.4,0,0.8,0.4,0.8,0.8V51.5z"/>
</g>
</g>
<g>
<g>
<path class="st6" d="M34.8,46.6c0-0.6,0.4-1.1,1-1.1s1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C35.2,47.6,34.8,47.2,34.8,46.6z"/>
</g>
<g>
<path class="st6" d="M38.3,46.6c0-0.6,0.4-1.1,1-1.1c0.6,0,1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C38.7,47.6,38.3,47.2,38.3,46.6z"/>
</g>
<g>
<path class="st6" d="M41.8,46.6c0-0.6,0.4-1.1,1-1.1s1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C42.2,47.6,41.8,47.2,41.8,46.6z"/>
</g>
</g>
</g>
<g>
<g>
<g>
<path class="st5" d="M46,35.5c0,0.4-0.4,0.8-0.8,0.8H33.4c-0.4,0-0.8-0.4-0.8-0.8v-9.9c0-0.4,0.4-0.8,0.8-0.8h11.9
c0.4,0,0.8,0.4,0.8,0.8V35.5z"/>
</g>
</g>
<g>
<g>
<path class="st6" d="M34.8,30.5c0-0.6,0.4-1.1,1-1.1s1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C35.2,31.6,34.8,31.1,34.8,30.5z"/>
</g>
<g>
<path class="st6" d="M38.3,30.5c0-0.6,0.4-1.1,1-1.1c0.6,0,1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C38.7,31.6,38.3,31.1,38.3,30.5z"/>
</g>
<g>
<path class="st6" d="M41.8,30.5c0-0.6,0.4-1.1,1-1.1s1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C42.2,31.6,41.8,31.1,41.8,30.5z"/>
</g>
</g>
</g>
<g>
<g>
<g>
<path class="st19" d="M46,67.6c0,0.4-0.4,0.8-0.8,0.8H33.4c-0.4,0-0.8-0.4-0.8-0.8v-9.9c0-0.4,0.4-0.8,0.8-0.8h11.9
c0.4,0,0.8,0.4,0.8,0.8V67.6z"/>
</g>
</g>
<g>
<g>
<path class="st6" d="M34.8,62.6c0-0.6,0.4-1.1,1-1.1s1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C35.2,63.7,34.8,63.2,34.8,62.6z"/>
</g>
<g>
<path class="st6" d="M38.3,62.6c0-0.6,0.4-1.1,1-1.1c0.6,0,1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C38.7,63.7,38.3,63.2,38.3,62.6z"/>
</g>
<g>
<path class="st6" d="M41.8,62.6c0-0.6,0.4-1.1,1-1.1s1,0.4,1,1.1c0,0.6-0.4,1.1-1,1.1C42.2,63.7,41.8,63.2,41.8,62.6z"/>
</g>
</g>
</g>
</g>
<g>
<path class="st6" d="M30.8,31.1h-5c-2,0-3.7-1.8-3.7-4v-2.7h1.4v2.7c0,1.4,1,2.6,2.3,2.6h5V31.1z"/>
</g>
<g>
<path class="st6" d="M61.3,53.2h-1.4v-3c0-1.3-1-2.3-2.3-2.3H48v-1.4h9.7c2,0,3.7,1.7,3.7,3.7V53.2z"/>
</g>
<g>
<rect x="53.4" y="55" class="st6" width="16.3" height="10"/>
</g>
<g>
<path class="st6" d="M57.6,45.4H48V44h9.7c1.3,0,2.3-1,2.3-2.3v-3h1.4v3C61.3,43.7,59.7,45.4,57.6,45.4z"/>
</g>
<g>
<path class="st6" d="M31.4,63.1H18.8c-2,0-3.7-1.8-3.7-4v-2.7h1.4v2.7c0,1.4,1,2.6,2.3,2.6h12.6V63.1z"/>
</g>
<g>
<polygon class="st36" points="68.5,37.6 53.7,37.6 53.7,22.8 63.7,22.8 68.5,27.3 "/>
<polygon class="st4" points="68.5,27.3 63.7,27.3 63.7,22.8 "/>
<g>
<rect x="55.9" y="26.2" class="st37" width="7.1" height="1.2"/>
<rect x="55.9" y="29.6" class="st37" width="10.4" height="1.2"/>
<rect x="55.9" y="33" class="st37" width="10.4" height="1.2"/>
</g>
</g>
<g>
<rect x="17.1" y="15.9" class="st37" width="12.5" height="1.3"/>
<rect x="17.1" y="18.4" class="st37" width="12.5" height="1.3"/>
</g>
<g>
<polygon class="st28" points="23.8,55.1 9,55.1 9,40.3 18.9,40.3 23.8,44.9 "/>
<polygon class="st4" points="23.8,44.9 19,44.9 19,40.3 "/>
<g>
<rect x="11.2" y="43.7" class="st4" width="7.1" height="1.2"/>
<rect x="11.2" y="47.2" class="st4" width="10.4" height="1.2"/>
<rect x="11.2" y="50.6" class="st4" width="10.4" height="1.2"/>
</g>
</g>
<g>
<rect x="55.8" y="57.7" class="st37" width="11.5" height="1.2"/>
<rect x="55.8" y="60.4" class="st37" width="11.5" height="1.2"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

2419
package-lock.json generated Normal file
View File

@ -0,0 +1,2419 @@
{
"name": "aurorxa",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "aurorxa",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"dayjs": "1.11.11",
"dotenv": "^16.4.5",
"font-pingfang-sc-font-weight-improved": "^1.0.7",
"medium-zoom": "^1.1.0",
"vitepress-plugin-comment-with-giscus": "^1.1.15"
},
"devDependencies": {
"@types/node": "^20.14.9",
"markdown-it-mathjax3": "^4.3.2",
"vitepress": "^1.3.1"
}
},
"node_modules/@algolia/autocomplete-core": {
"version": "1.9.3",
"resolved": "https://registry.npmmirror.com/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz",
"integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/autocomplete-plugin-algolia-insights": "1.9.3",
"@algolia/autocomplete-shared": "1.9.3"
}
},
"node_modules/@algolia/autocomplete-plugin-algolia-insights": {
"version": "1.9.3",
"resolved": "https://registry.npmmirror.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz",
"integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/autocomplete-shared": "1.9.3"
},
"peerDependencies": {
"search-insights": ">= 1 < 3"
}
},
"node_modules/@algolia/autocomplete-preset-algolia": {
"version": "1.9.3",
"resolved": "https://registry.npmmirror.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz",
"integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/autocomplete-shared": "1.9.3"
},
"peerDependencies": {
"@algolia/client-search": ">= 4.9.1 < 6",
"algoliasearch": ">= 4.9.1 < 6"
}
},
"node_modules/@algolia/autocomplete-shared": {
"version": "1.9.3",
"resolved": "https://registry.npmmirror.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz",
"integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"@algolia/client-search": ">= 4.9.1 < 6",
"algoliasearch": ">= 4.9.1 < 6"
}
},
"node_modules/@algolia/cache-browser-local-storage": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz",
"integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/cache-common": "4.24.0"
}
},
"node_modules/@algolia/cache-common": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/cache-common/-/cache-common-4.24.0.tgz",
"integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==",
"dev": true,
"license": "MIT"
},
"node_modules/@algolia/cache-in-memory": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz",
"integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/cache-common": "4.24.0"
}
},
"node_modules/@algolia/client-account": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/client-account/-/client-account-4.24.0.tgz",
"integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/client-common": "4.24.0",
"@algolia/client-search": "4.24.0",
"@algolia/transporter": "4.24.0"
}
},
"node_modules/@algolia/client-analytics": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/client-analytics/-/client-analytics-4.24.0.tgz",
"integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/client-common": "4.24.0",
"@algolia/client-search": "4.24.0",
"@algolia/requester-common": "4.24.0",
"@algolia/transporter": "4.24.0"
}
},
"node_modules/@algolia/client-common": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/client-common/-/client-common-4.24.0.tgz",
"integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/requester-common": "4.24.0",
"@algolia/transporter": "4.24.0"
}
},
"node_modules/@algolia/client-personalization": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/client-personalization/-/client-personalization-4.24.0.tgz",
"integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/client-common": "4.24.0",
"@algolia/requester-common": "4.24.0",
"@algolia/transporter": "4.24.0"
}
},
"node_modules/@algolia/client-search": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/client-search/-/client-search-4.24.0.tgz",
"integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/client-common": "4.24.0",
"@algolia/requester-common": "4.24.0",
"@algolia/transporter": "4.24.0"
}
},
"node_modules/@algolia/logger-common": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/logger-common/-/logger-common-4.24.0.tgz",
"integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==",
"dev": true,
"license": "MIT"
},
"node_modules/@algolia/logger-console": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/logger-console/-/logger-console-4.24.0.tgz",
"integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/logger-common": "4.24.0"
}
},
"node_modules/@algolia/recommend": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/recommend/-/recommend-4.24.0.tgz",
"integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/cache-browser-local-storage": "4.24.0",
"@algolia/cache-common": "4.24.0",
"@algolia/cache-in-memory": "4.24.0",
"@algolia/client-common": "4.24.0",
"@algolia/client-search": "4.24.0",
"@algolia/logger-common": "4.24.0",
"@algolia/logger-console": "4.24.0",
"@algolia/requester-browser-xhr": "4.24.0",
"@algolia/requester-common": "4.24.0",
"@algolia/requester-node-http": "4.24.0",
"@algolia/transporter": "4.24.0"
}
},
"node_modules/@algolia/requester-browser-xhr": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz",
"integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/requester-common": "4.24.0"
}
},
"node_modules/@algolia/requester-common": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/requester-common/-/requester-common-4.24.0.tgz",
"integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==",
"dev": true,
"license": "MIT"
},
"node_modules/@algolia/requester-node-http": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz",
"integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/requester-common": "4.24.0"
}
},
"node_modules/@algolia/transporter": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/@algolia/transporter/-/transporter-4.24.0.tgz",
"integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/cache-common": "4.24.0",
"@algolia/logger-common": "4.24.0",
"@algolia/requester-common": "4.24.0"
}
},
"node_modules/@babel/parser": {
"version": "7.24.8",
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.24.8.tgz",
"integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==",
"license": "MIT",
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@docsearch/css": {
"version": "3.6.1",
"resolved": "https://registry.npmmirror.com/@docsearch/css/-/css-3.6.1.tgz",
"integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==",
"dev": true,
"license": "MIT"
},
"node_modules/@docsearch/js": {
"version": "3.6.1",
"resolved": "https://registry.npmmirror.com/@docsearch/js/-/js-3.6.1.tgz",
"integrity": "sha512-erI3RRZurDr1xES5hvYJ3Imp7jtrXj6f1xYIzDzxiS7nNBufYWPbJwrmMqWC5g9y165PmxEmN9pklGCdLi0Iqg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@docsearch/react": "3.6.1",
"preact": "^10.0.0"
}
},
"node_modules/@docsearch/react": {
"version": "3.6.1",
"resolved": "https://registry.npmmirror.com/@docsearch/react/-/react-3.6.1.tgz",
"integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/autocomplete-core": "1.9.3",
"@algolia/autocomplete-preset-algolia": "1.9.3",
"@docsearch/css": "3.6.1",
"algoliasearch": "^4.19.1"
},
"peerDependencies": {
"@types/react": ">= 16.8.0 < 19.0.0",
"react": ">= 16.8.0 < 19.0.0",
"react-dom": ">= 16.8.0 < 19.0.0",
"search-insights": ">= 1 < 3"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
},
"search-insights": {
"optional": true
}
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
"integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
"integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
"integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
"integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
"integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
"integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
"integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
"integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
"integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
"integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
"integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
"integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
"integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
"integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
"integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
"integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
"integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
"integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
"integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
"integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@giscus/vue": {
"version": "2.4.0",
"resolved": "https://registry.npmmirror.com/@giscus/vue/-/vue-2.4.0.tgz",
"integrity": "sha512-QOxKHgsMT91myyQagP2v20YYAei1ByZuc3qcaYxbHx4AwOeyVrybDIuRFwG9YDv6OraC86jYnU4Ixd37ddC/0A==",
"dependencies": {
"giscus": "^1.4.0"
},
"peerDependencies": {
"vue": ">=3.2.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"license": "MIT"
},
"node_modules/@lit-labs/ssr-dom-shim": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
"integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==",
"license": "BSD-3-Clause"
},
"node_modules/@lit/reactive-element": {
"version": "2.0.4",
"resolved": "https://registry.npmmirror.com/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
"integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.2.0"
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz",
"integrity": "sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz",
"integrity": "sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz",
"integrity": "sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz",
"integrity": "sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz",
"integrity": "sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz",
"integrity": "sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz",
"integrity": "sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz",
"integrity": "sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz",
"integrity": "sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz",
"integrity": "sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz",
"integrity": "sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz",
"integrity": "sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz",
"integrity": "sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz",
"integrity": "sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz",
"integrity": "sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz",
"integrity": "sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@shikijs/core": {
"version": "1.11.1",
"resolved": "https://registry.npmmirror.com/@shikijs/core/-/core-1.11.1.tgz",
"integrity": "sha512-Qsn8h15SWgv5TDRoDmiHNzdQO2BxDe86Yq6vIHf5T0cCvmfmccJKIzHtep8bQO9HMBZYCtCBzaXdd1MnxZBPSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/hast": "^3.0.4"
}
},
"node_modules/@shikijs/transformers": {
"version": "1.11.1",
"resolved": "https://registry.npmmirror.com/@shikijs/transformers/-/transformers-1.11.1.tgz",
"integrity": "sha512-e6DUvZRylv+V8htF5q3ZuNyPaxJYQnsLyTd2S/K6ePs8t132NJS82LG2vARmtfSFP3I3CcBXfJ73FaCgI9kAMg==",
"dev": true,
"license": "MIT",
"dependencies": {
"shiki": "1.11.1"
}
},
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/hast": {
"version": "3.0.4",
"resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz",
"integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/unist": "*"
}
},
"node_modules/@types/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/@types/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/markdown-it": {
"version": "14.1.1",
"resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-14.1.1.tgz",
"integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/linkify-it": "^5",
"@types/mdurl": "^2"
}
},
"node_modules/@types/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/@types/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.14.12",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-20.14.12.tgz",
"integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"license": "MIT"
},
"node_modules/@types/unist": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.2.tgz",
"integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.20",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
"dev": true,
"license": "MIT"
},
"node_modules/@vitejs/plugin-vue": {
"version": "5.1.0",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.1.0.tgz",
"integrity": "sha512-QMRxARyrdiwi1mj3AW4fLByoHTavreXq0itdEW696EihXglf1MB3D4C2gBvE0jMPH29ZjC3iK8aIaUMLf4EOGA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"peerDependencies": {
"vite": "^5.0.0",
"vue": "^3.2.25"
}
},
"node_modules/@vue/compiler-core": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.4.33.tgz",
"integrity": "sha512-MoIREbkdPQlnGfSKDMgzTqzqx5nmEjIc0ydLVYlTACGBsfvOJ4tHSbZXKVF536n6fB+0eZaGEOqsGThPpdvF5A==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.24.7",
"@vue/shared": "3.4.33",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-core/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.4.33.tgz",
"integrity": "sha512-GzB8fxEHKw0gGet5BKlpfXEqoBnzSVWwMnT+dc25wE7pFEfrU/QsvjZMP9rD4iVXHBBoemTct8mN0GJEI6ZX5A==",
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.4.33",
"@vue/shared": "3.4.33"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.4.33.tgz",
"integrity": "sha512-7rk7Vbkn21xMwIUpHQR4hCVejwE6nvhBOiDgoBcR03qvGqRKA7dCBSsHZhwhYUsmjlbJ7OtD5UFIyhP6BY+c8A==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.24.7",
"@vue/compiler-core": "3.4.33",
"@vue/compiler-dom": "3.4.33",
"@vue/compiler-ssr": "3.4.33",
"@vue/shared": "3.4.33",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.10",
"postcss": "^8.4.39",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.4.33.tgz",
"integrity": "sha512-0WveC9Ai+eT/1b6LCV5IfsufBZ0HP7pSSTdDjcuW302tTEgoBw8rHVHKPbGUtzGReUFCRXbv6zQDDgucnV2WzQ==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.4.33",
"@vue/shared": "3.4.33"
}
},
"node_modules/@vue/devtools-api": {
"version": "7.3.7",
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.3.7.tgz",
"integrity": "sha512-kvjQ6nmsqTp7SrmpwI2G0MgbC4ys0bPsgQirHXJM8y1m7siQ5RnWQUHJVfyUrHNguCySW1cevAdIw87zrPTl9g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^7.3.7"
}
},
"node_modules/@vue/devtools-kit": {
"version": "7.3.7",
"resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.3.7.tgz",
"integrity": "sha512-ktHhhjI4CoUrwdSUF5b/MFfjrtAtK8r4vhOkFyRN5Yp9kdXTwsRBYcwarHuP+wFPKf4/KM7DVBj2ELO8SBwdsw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/devtools-shared": "^7.3.7",
"birpc": "^0.2.17",
"hookable": "^5.5.3",
"mitt": "^3.0.1",
"perfect-debounce": "^1.0.0",
"speakingurl": "^14.0.1",
"superjson": "^2.2.1"
}
},
"node_modules/@vue/devtools-shared": {
"version": "7.3.7",
"resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.3.7.tgz",
"integrity": "sha512-M9EU1/bWi5GNS/+IZrAhwGOVZmUTN4MH22Hvh35nUZZg9AZP2R2OhfCb+MG4EtAsrUEYlu3R43/SIj3G7EZYtQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"rfdc": "^1.4.1"
}
},
"node_modules/@vue/reactivity": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.4.33.tgz",
"integrity": "sha512-B24QIelahDbyHipBgbUItQblbd4w5HpG3KccL+YkGyo3maXyS253FzcTR3pSz739OTphmzlxP7JxEMWBpewilA==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.4.33"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.4.33.tgz",
"integrity": "sha512-6wavthExzT4iAxpe8q37/rDmf44nyOJGISJPxCi9YsQO+8w9v0gLCFLfH5TzD1V1AYrTAdiF4Y1cgUmP68jP6w==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.4.33",
"@vue/shared": "3.4.33"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.4.33.tgz",
"integrity": "sha512-iHsMCUSFJ+4z432Bn9kZzHX+zOXa6+iw36DaVRmKYZpPt9jW9riF32SxNwB124i61kp9+AZtheQ/mKoJLerAaQ==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.4.33",
"@vue/runtime-core": "3.4.33",
"@vue/shared": "3.4.33",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.4.33.tgz",
"integrity": "sha512-jTH0d6gQcaYideFP/k0WdEu8PpRS9MF8d0b6SfZzNi+ap972pZ0TNIeTaESwdOtdY0XPVj54XEJ6K0wXxir4fw==",
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.4.33",
"@vue/shared": "3.4.33"
},
"peerDependencies": {
"vue": "3.4.33"
}
},
"node_modules/@vue/shared": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.4.33.tgz",
"integrity": "sha512-aoRY0jQk3A/cuvdkodTrM4NMfxco8n55eG4H7ML/CRy7OryHfiqvug4xrCBBMbbN+dvXAetDDwZW9DXWWjBntA==",
"license": "MIT"
},
"node_modules/@vueuse/core": {
"version": "10.11.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-10.11.0.tgz",
"integrity": "sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.20",
"@vueuse/metadata": "10.11.0",
"@vueuse/shared": "10.11.0",
"vue-demi": ">=0.14.8"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.9",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.9.tgz",
"integrity": "sha512-dC1TJMODGM8lxhP6wLToncaDPPNB3biVxxRDuNCYpuXwi70ou7NsGd97KVTJ2omepGId429JZt8oaZKeXbqxwg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/integrations": {
"version": "10.11.0",
"resolved": "https://registry.npmmirror.com/@vueuse/integrations/-/integrations-10.11.0.tgz",
"integrity": "sha512-Pp6MtWEIr+NDOccWd8j59Kpjy5YDXogXI61Kb1JxvSfVBO8NzFQkmrKmSZz47i+ZqHnIzxaT38L358yDHTncZg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vueuse/core": "10.11.0",
"@vueuse/shared": "10.11.0",
"vue-demi": ">=0.14.8"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"async-validator": "^4",
"axios": "^1",
"change-case": "^4",
"drauu": "^0.3",
"focus-trap": "^7",
"fuse.js": "^6",
"idb-keyval": "^6",
"jwt-decode": "^3",
"nprogress": "^0.2",
"qrcode": "^1.5",
"sortablejs": "^1",
"universal-cookie": "^6"
},
"peerDependenciesMeta": {
"async-validator": {
"optional": true
},
"axios": {
"optional": true
},
"change-case": {
"optional": true
},
"drauu": {
"optional": true
},
"focus-trap": {
"optional": true
},
"fuse.js": {
"optional": true
},
"idb-keyval": {
"optional": true
},
"jwt-decode": {
"optional": true
},
"nprogress": {
"optional": true
},
"qrcode": {
"optional": true
},
"sortablejs": {
"optional": true
},
"universal-cookie": {
"optional": true
}
}
},
"node_modules/@vueuse/integrations/node_modules/vue-demi": {
"version": "0.14.9",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.9.tgz",
"integrity": "sha512-dC1TJMODGM8lxhP6wLToncaDPPNB3biVxxRDuNCYpuXwi70ou7NsGd97KVTJ2omepGId429JZt8oaZKeXbqxwg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/metadata": {
"version": "10.11.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-10.11.0.tgz",
"integrity": "sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "10.11.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-10.11.0.tgz",
"integrity": "sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==",
"dev": true,
"license": "MIT",
"dependencies": {
"vue-demi": ">=0.14.8"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.9",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.9.tgz",
"integrity": "sha512-dC1TJMODGM8lxhP6wLToncaDPPNB3biVxxRDuNCYpuXwi70ou7NsGd97KVTJ2omepGId429JZt8oaZKeXbqxwg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/algoliasearch": {
"version": "4.24.0",
"resolved": "https://registry.npmmirror.com/algoliasearch/-/algoliasearch-4.24.0.tgz",
"integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@algolia/cache-browser-local-storage": "4.24.0",
"@algolia/cache-common": "4.24.0",
"@algolia/cache-in-memory": "4.24.0",
"@algolia/client-account": "4.24.0",
"@algolia/client-analytics": "4.24.0",
"@algolia/client-common": "4.24.0",
"@algolia/client-personalization": "4.24.0",
"@algolia/client-search": "4.24.0",
"@algolia/logger-common": "4.24.0",
"@algolia/logger-console": "4.24.0",
"@algolia/recommend": "4.24.0",
"@algolia/requester-browser-xhr": "4.24.0",
"@algolia/requester-common": "4.24.0",
"@algolia/requester-node-http": "4.24.0",
"@algolia/transporter": "4.24.0"
}
},
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.3.tgz",
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/birpc": {
"version": "0.2.17",
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-0.2.17.tgz",
"integrity": "sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true,
"license": "ISC"
},
"node_modules/cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.0.0-rc.10.tgz",
"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
"dev": true,
"license": "MIT",
"dependencies": {
"cheerio-select": "^1.5.0",
"dom-serializer": "^1.3.2",
"domhandler": "^4.2.0",
"htmlparser2": "^6.1.0",
"parse5": "^6.0.1",
"parse5-htmlparser2-tree-adapter": "^6.0.1",
"tslib": "^2.2.0"
},
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
}
},
"node_modules/cheerio-select": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-1.6.0.tgz",
"integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"css-select": "^4.3.0",
"css-what": "^6.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.3.1",
"domutils": "^2.8.0"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/commander": {
"version": "6.2.1",
"resolved": "https://registry.npmmirror.com/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/copy-anything": {
"version": "3.0.5",
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-what": "^4.1.8"
},
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/css-select": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz",
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.0.1",
"domhandler": "^4.3.1",
"domutils": "^2.8.0",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT"
},
"node_modules/dayjs": {
"version": "1.11.11",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.11.tgz",
"integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==",
"license": "MIT"
},
"node_modules/dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"dev": true,
"license": "MIT",
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "BSD-2-Clause"
},
"node_modules/domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.2.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dotenv": {
"version": "16.4.5",
"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/entities": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"dev": true,
"license": "BSD-2-Clause",
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/esbuild": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz",
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.21.5",
"@esbuild/android-arm": "0.21.5",
"@esbuild/android-arm64": "0.21.5",
"@esbuild/android-x64": "0.21.5",
"@esbuild/darwin-arm64": "0.21.5",
"@esbuild/darwin-x64": "0.21.5",
"@esbuild/freebsd-arm64": "0.21.5",
"@esbuild/freebsd-x64": "0.21.5",
"@esbuild/linux-arm": "0.21.5",
"@esbuild/linux-arm64": "0.21.5",
"@esbuild/linux-ia32": "0.21.5",
"@esbuild/linux-loong64": "0.21.5",
"@esbuild/linux-mips64el": "0.21.5",
"@esbuild/linux-ppc64": "0.21.5",
"@esbuild/linux-riscv64": "0.21.5",
"@esbuild/linux-s390x": "0.21.5",
"@esbuild/linux-x64": "0.21.5",
"@esbuild/netbsd-x64": "0.21.5",
"@esbuild/openbsd-x64": "0.21.5",
"@esbuild/sunos-x64": "0.21.5",
"@esbuild/win32-arm64": "0.21.5",
"@esbuild/win32-ia32": "0.21.5",
"@esbuild/win32-x64": "0.21.5"
}
},
"node_modules/escape-goat": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/escape-goat/-/escape-goat-3.0.0.tgz",
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/esm": {
"version": "3.2.25",
"resolved": "https://registry.npmmirror.com/esm/-/esm-3.2.25.tgz",
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"license": "MIT"
},
"node_modules/focus-trap": {
"version": "7.5.4",
"resolved": "https://registry.npmmirror.com/focus-trap/-/focus-trap-7.5.4.tgz",
"integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==",
"dev": true,
"license": "MIT",
"dependencies": {
"tabbable": "^6.2.0"
}
},
"node_modules/font-pingfang-sc-font-weight-improved": {
"version": "1.0.7",
"resolved": "https://registry.npmmirror.com/font-pingfang-sc-font-weight-improved/-/font-pingfang-sc-font-weight-improved-1.0.7.tgz",
"integrity": "sha512-wF4Z9q5/pBg/Vo1JJjQqcSVEoWNqyeVP0B/bqqi/8uKUKAI+fCVlMvNIGEG0O7d0Mb3TNKgYGiAz4nVBVC5epw==",
"license": "ISC"
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/giscus": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/giscus/-/giscus-1.5.0.tgz",
"integrity": "sha512-t3LL0qbSO3JXq3uyQeKpF5CegstGfKX/0gI6eDe1cmnI7D56R7j52yLdzw4pdKrg3VnufwCgCM3FDz7G1Qr6lg==",
"license": "MIT",
"dependencies": {
"lit": "^3.1.2"
}
},
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"dev": true,
"license": "MIT"
},
"node_modules/htmlparser2": {
"version": "6.1.0",
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz",
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
"dev": true,
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "MIT",
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"domutils": "^2.5.2",
"entities": "^2.0.0"
}
},
"node_modules/is-what": {
"version": "4.1.16",
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
"integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/juice": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/juice/-/juice-8.1.0.tgz",
"integrity": "sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"cheerio": "1.0.0-rc.10",
"commander": "^6.1.0",
"mensch": "^0.3.4",
"slick": "^1.12.2",
"web-resource-inliner": "^6.0.1"
},
"bin": {
"juice": "bin/juice"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/lit": {
"version": "3.1.4",
"resolved": "https://registry.npmmirror.com/lit/-/lit-3.1.4.tgz",
"integrity": "sha512-q6qKnKXHy2g1kjBaNfcoLlgbI3+aSOZ9Q4tiGa9bGYXq5RBXxkVTqTIVmP2VWMp29L4GyvCFm8ZQ2o56eUAMyA==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit/reactive-element": "^2.0.4",
"lit-element": "^4.0.4",
"lit-html": "^3.1.2"
}
},
"node_modules/lit-element": {
"version": "4.0.6",
"resolved": "https://registry.npmmirror.com/lit-element/-/lit-element-4.0.6.tgz",
"integrity": "sha512-U4sdJ3CSQip7sLGZ/uJskO5hGiqtlpxndsLr6mt3IQIjheg93UKYeGQjWMRql1s/cXNOaRrCzC2FQwjIwSUqkg==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.2.0",
"@lit/reactive-element": "^2.0.4",
"lit-html": "^3.1.2"
}
},
"node_modules/lit-html": {
"version": "3.1.4",
"resolved": "https://registry.npmmirror.com/lit-html/-/lit-html-3.1.4.tgz",
"integrity": "sha512-yKKO2uVv7zYFHlWMfZmqc+4hkmSbFp8jgjdZY9vvR9jr4J8fH6FUMXhr+ljfELgmjpvlF7Z1SJ5n5/Jeqtc9YA==",
"license": "BSD-3-Clause",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/magic-string": {
"version": "0.30.10",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.10.tgz",
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
}
},
"node_modules/mark.js": {
"version": "8.11.1",
"resolved": "https://registry.npmmirror.com/mark.js/-/mark.js-8.11.1.tgz",
"integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==",
"dev": true,
"license": "MIT"
},
"node_modules/markdown-it-mathjax3": {
"version": "4.3.2",
"resolved": "https://registry.npmmirror.com/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz",
"integrity": "sha512-TX3GW5NjmupgFtMJGRauioMbbkGsOXAAt1DZ/rzzYmTHqzkO1rNAdiMD4NiruurToPApn2kYy76x02QN26qr2w==",
"dev": true,
"license": "MIT",
"dependencies": {
"juice": "^8.0.0",
"mathjax-full": "^3.2.0"
}
},
"node_modules/mathjax-full": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/mathjax-full/-/mathjax-full-3.2.2.tgz",
"integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"esm": "^3.2.25",
"mhchemparser": "^4.1.0",
"mj-context-menu": "^0.6.1",
"speech-rule-engine": "^4.0.6"
}
},
"node_modules/medium-zoom": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/medium-zoom/-/medium-zoom-1.1.0.tgz",
"integrity": "sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==",
"license": "MIT"
},
"node_modules/mensch": {
"version": "0.3.4",
"resolved": "https://registry.npmmirror.com/mensch/-/mensch-0.3.4.tgz",
"integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==",
"dev": true,
"license": "MIT"
},
"node_modules/mhchemparser": {
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/mhchemparser/-/mhchemparser-4.2.1.tgz",
"integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"dev": true,
"license": "MIT",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/minisearch": {
"version": "7.1.0",
"resolved": "https://registry.npmmirror.com/minisearch/-/minisearch-7.1.0.tgz",
"integrity": "sha512-tv7c/uefWdEhcu6hvrfTihflgeEi2tN6VV7HJnCjK6VxM75QQJh4t9FwJCsA2EsRS8LCnu3W87CuGPWMocOLCA==",
"dev": true,
"license": "MIT"
},
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"dev": true,
"license": "MIT"
},
"node_modules/mj-context-menu": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
"integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dev": true,
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
"dev": true,
"license": "MIT"
},
"node_modules/parse5-htmlparser2-tree-adapter": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
"dev": true,
"license": "MIT",
"dependencies": {
"parse5": "^6.0.1"
}
},
"node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
"dev": true,
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz",
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.4.39",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.39.tgz",
"integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.1",
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/preact": {
"version": "10.23.0",
"resolved": "https://registry.npmmirror.com/preact/-/preact-10.23.0.tgz",
"integrity": "sha512-Pox0jeY4q6PGkFB5AsXni+zHxxx/sAYFIFZzukW4nIpoJLRziRX0xC4WjZENlkSrDQvqVgZcaZzZ/NL8/A+H/w==",
"dev": true,
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"dev": true,
"license": "MIT"
},
"node_modules/rollup": {
"version": "4.19.0",
"resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.19.0.tgz",
"integrity": "sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.5"
},
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.19.0",
"@rollup/rollup-android-arm64": "4.19.0",
"@rollup/rollup-darwin-arm64": "4.19.0",
"@rollup/rollup-darwin-x64": "4.19.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.19.0",
"@rollup/rollup-linux-arm-musleabihf": "4.19.0",
"@rollup/rollup-linux-arm64-gnu": "4.19.0",
"@rollup/rollup-linux-arm64-musl": "4.19.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.19.0",
"@rollup/rollup-linux-riscv64-gnu": "4.19.0",
"@rollup/rollup-linux-s390x-gnu": "4.19.0",
"@rollup/rollup-linux-x64-gnu": "4.19.0",
"@rollup/rollup-linux-x64-musl": "4.19.0",
"@rollup/rollup-win32-arm64-msvc": "4.19.0",
"@rollup/rollup-win32-ia32-msvc": "4.19.0",
"@rollup/rollup-win32-x64-msvc": "4.19.0",
"fsevents": "~2.3.2"
}
},
"node_modules/search-insights": {
"version": "2.15.0",
"resolved": "https://registry.npmmirror.com/search-insights/-/search-insights-2.15.0.tgz",
"integrity": "sha512-ch2sPCUDD4sbPQdknVl9ALSi9H7VyoeVbsxznYz6QV55jJ8CI3EtwpO1i84keN4+hF5IeHWIeGvc08530JkVXQ==",
"dev": true,
"license": "MIT",
"peer": true
},
"node_modules/shiki": {
"version": "1.11.1",
"resolved": "https://registry.npmmirror.com/shiki/-/shiki-1.11.1.tgz",
"integrity": "sha512-VHD3Q0EBXaaa245jqayBe5zQyMQUdXBFjmGr9MpDaDpAKRMYn7Ff00DM5MLk26UyKjnml3yQ0O2HNX7PtYVNFQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@shikijs/core": "1.11.1",
"@types/hast": "^3.0.4"
}
},
"node_modules/slick": {
"version": "1.12.2",
"resolved": "https://registry.npmmirror.com/slick/-/slick-1.12.2.tgz",
"integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==",
"dev": true,
"license": "MIT (http://mootools.net/license.txt)",
"engines": {
"node": "*"
}
},
"node_modules/source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/speakingurl": {
"version": "14.0.1",
"resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/speech-rule-engine": {
"version": "4.0.7",
"resolved": "https://registry.npmmirror.com/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz",
"integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"commander": "9.2.0",
"wicked-good-xpath": "1.3.0",
"xmldom-sre": "0.1.31"
},
"bin": {
"sre": "bin/sre"
}
},
"node_modules/speech-rule-engine/node_modules/commander": {
"version": "9.2.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-9.2.0.tgz",
"integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/superjson": {
"version": "2.2.1",
"resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.1.tgz",
"integrity": "sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==",
"dev": true,
"license": "MIT",
"dependencies": {
"copy-anything": "^3.0.2"
},
"engines": {
"node": ">=16"
}
},
"node_modules/tabbable": {
"version": "6.2.0",
"resolved": "https://registry.npmmirror.com/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
"dev": true,
"license": "MIT"
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"dev": true,
"license": "MIT"
},
"node_modules/tslib": {
"version": "2.6.3",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.3.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
"dev": true,
"license": "0BSD"
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true,
"license": "MIT"
},
"node_modules/valid-data-url": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/valid-data-url/-/valid-data-url-3.0.1.tgz",
"integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/vite": {
"version": "5.3.4",
"resolved": "https://registry.npmmirror.com/vite/-/vite-5.3.4.tgz",
"integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.39",
"rollup": "^4.13.0"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
},
"peerDependencies": {
"@types/node": "^18.0.0 || >=20.0.0",
"less": "*",
"lightningcss": "^1.21.0",
"sass": "*",
"stylus": "*",
"sugarss": "*",
"terser": "^5.4.0"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
},
"less": {
"optional": true
},
"lightningcss": {
"optional": true
},
"sass": {
"optional": true
},
"stylus": {
"optional": true
},
"sugarss": {
"optional": true
},
"terser": {
"optional": true
}
}
},
"node_modules/vitepress": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/vitepress/-/vitepress-1.3.1.tgz",
"integrity": "sha512-soZDpg2rRVJNIM/IYMNDPPr+zTHDA5RbLDHAxacRu+Q9iZ2GwSR0QSUlLs+aEZTkG0SOX1dc8RmUYwyuxK8dfQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@docsearch/css": "^3.6.0",
"@docsearch/js": "^3.6.0",
"@shikijs/core": "^1.10.3",
"@shikijs/transformers": "^1.10.3",
"@types/markdown-it": "^14.1.1",
"@vitejs/plugin-vue": "^5.0.5",
"@vue/devtools-api": "^7.3.5",
"@vue/shared": "^3.4.31",
"@vueuse/core": "^10.11.0",
"@vueuse/integrations": "^10.11.0",
"focus-trap": "^7.5.4",
"mark.js": "8.11.1",
"minisearch": "^7.0.0",
"shiki": "^1.10.3",
"vite": "^5.3.3",
"vue": "^3.4.31"
},
"bin": {
"vitepress": "bin/vitepress.js"
},
"peerDependencies": {
"markdown-it-mathjax3": "^4",
"postcss": "^8"
},
"peerDependenciesMeta": {
"markdown-it-mathjax3": {
"optional": true
},
"postcss": {
"optional": true
}
}
},
"node_modules/vitepress-plugin-comment-with-giscus": {
"version": "1.1.15",
"resolved": "https://registry.npmmirror.com/vitepress-plugin-comment-with-giscus/-/vitepress-plugin-comment-with-giscus-1.1.15.tgz",
"integrity": "sha512-1DJjgN+7SYvn5ZkjuSXPmz7nlqfcrh4qCGGviiZghA2ELXnaO2m9WY7m+RisPSaqCn90xqe0JbO2T4NMq8iUBg==",
"license": "ISC",
"dependencies": {
"@giscus/vue": "^2.2.8"
}
},
"node_modules/vue": {
"version": "3.4.33",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.4.33.tgz",
"integrity": "sha512-VdMCWQOummbhctl4QFMcW6eNtXHsFyDlX60O/tsSQuCcuDOnJ1qPOhhVla65Niece7xq/P2zyZReIO5mP+LGTQ==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.4.33",
"@vue/compiler-sfc": "3.4.33",
"@vue/runtime-dom": "3.4.33",
"@vue/server-renderer": "3.4.33",
"@vue/shared": "3.4.33"
},
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/web-resource-inliner": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz",
"integrity": "sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-colors": "^4.1.1",
"escape-goat": "^3.0.0",
"htmlparser2": "^5.0.0",
"mime": "^2.4.6",
"node-fetch": "^2.6.0",
"valid-data-url": "^3.0.0"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/web-resource-inliner/node_modules/domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.0.1"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/htmlparser2": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-5.0.1.tgz",
"integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^3.3.0",
"domutils": "^2.4.2",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/fb55/htmlparser2?sponsor=1"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"dev": true,
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dev": true,
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/wicked-good-xpath": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
"integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==",
"dev": true,
"license": "MIT"
},
"node_modules/xmldom-sre": {
"version": "0.1.31",
"resolved": "https://registry.npmmirror.com/xmldom-sre/-/xmldom-sre-0.1.31.tgz",
"integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==",
"dev": true,
"license": "(LGPL-2.0 or MIT)",
"engines": {
"node": ">=0.1"
}
}
}
}

26
package.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "aurorxa",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"docs:dev": "vitepress dev docs --mode development",
"docs:build": "vitepress build docs --mode production",
"docs:preview": "vitepress preview docs"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^20.14.9",
"markdown-it-mathjax3": "^4.3.2",
"vitepress": "^1.3.1"
},
"dependencies": {
"dayjs": "1.11.11",
"dotenv": "^16.4.5",
"font-pingfang-sc-font-weight-improved": "^1.0.7",
"medium-zoom": "^1.1.0",
"vitepress-plugin-comment-with-giscus": "^1.1.15"
}
}