在for循环和while循环中,都可以使用保留字else来实现扩展模式。
时间: 2024-12-20 07:29:24 浏览: 8
在Python中,`for` 和 `while` 循环都可以通过添加一个 `else` 子句来进行扩展,但这适用于两种循环的不同情况:
1. **for** 循环的 `else` 子句:通常用于`break`跳出循环的情况,当循环正常完成而没有遇到`break`语句时,才会执行`else`块里的代码。例如,你在寻找特定元素并遍历列表时,如果没有找到就执行`else`里的内容,表示已检查过所有元素。
```python
for item in items:
if condition:
break
else:
# 这里会在遍历完items且未遇到满足条件的item时执行
```
2. **while** 循环的 `else` 子句:它会在循环条件变为假(`False`)且循环体被执行完毕后执行。这意味着只要循环继续运行,`else` 就不会触发。这常用于需要检查循环是否被中断的情况。
```python
while condition:
# 循环体...
else:
# 当条件变为False时(即循环结束,未因`break`退出),执行此块
```
总的来说,`else` 帮助我们更清晰地组织代码结构,区分了循环的正常终止和意外提前终止情况。
相关问题
用c语言编写一个pl/0词法分析器程序扩展1. 支持数组功能,至少支持一维数组。2. 支持记录类型。3. 支持for循环语句。4. 支持swich语句。5. 支持if else语句。6. 支持浮点型或其他类型的数据。7. 支持++、--运算。
对于这个问题,需要先了解PL/0语言的基本语法和词法规则。
PL/0语言是一种简单的过程化编程语言,它具有类似于Pascal的语法。下面是PL/0语言的基本语法:
```
program = block "." .
block = [ "const" ident "=" number {"," ident "=" number} ";"]
[ "var" ident {"," ident} ";"]
{ "procedure" ident ";" block ";" } statement .
statement = [ ident ":=" expression | "call" ident
| "?" ident | "!" expression
| "begin" statement {";" statement } "end"
| "if" condition "then" statement
| "while" condition "do" statement
| "for" ident ":=" expression "to" expression "do" statement
| "switch" expression "case" expression ":" statement {";" expression ":" statement} ["default" ":" statement] "endswitch"
| "if" condition "then" statement ["else" statement]
].
condition = "odd" expression |
expression ("="|"#"|"<"|"<="|">"|">=") expression .
expression = [ "+"|"-"] term { ("+"|"-") term} .
term = factor {("*"|"/") factor} .
factor = ident | number | "(" expression ")" | "not" factor | "++" ident | "--" ident.
number = digit { digit } .
ident = letter { letter | digit } .
letter = "a" | "b" | ... | "z" | "A" | "B" | ... | "Z" .
digit = "0" | "1" | ... | "9" .
```
其中,ident表示标识符,number表示数字,letter表示字母,digit表示数字。PL/0语言的词法规则可以根据上面的语法规则推导出来。
下面是一个扩展了上述功能的PL/0词法分析器程序:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_IDENT_LEN 100 // 标识符最大长度
#define MAX_NUM_LEN 100 // 数字最大长度
typedef enum {
NONE, // 无类型
IDENT, // 标识符
NUMBER, // 数字
RESERVED, // 保留字
SYMBOL // 符号
} TokenType;
typedef enum {
// 保留字
CONST, VAR, PROCEDURE, BEGIN, END, CALL, IF, THEN, ELSE, WHILE, DO, FOR, TO, SWITCH, CASE, DEFAULT, ENDSWITCH,
// 符号
PLUS, MINUS, MUL, DIV, LPAREN, RPAREN, COMMA, SEMICOLON, PERIOD, COLON, ASSIGN, EQ, NEQ, LT, GT, LE, GE,
// 扩展
LBRACK, RBRACK, RECORD, DOT, INC, DEC
} TokenCode;
typedef struct {
TokenCode code; // 类型码
char lexeme[MAX_IDENT_LEN + 1]; // 词素
int lineNo; // 行号
TokenType type; // 类型
int value; // 值
} Token;
const char *reservedWords[] = {
"const", "var", "procedure", "begin", "end", "call", "if", "then", "else", "while", "do", "for", "to", "switch", "case", "default", "endswitch", NULL
};
const char *symbols[] = {
"+", "-", "*", "/", "(", ")", ",", ";", ".", ":", ":=", "=", "<>", "<", ">", "<=", ">=", "[", "]", "record", "->", "++", "--", NULL
};
TokenCode getReservedWordCode(const char *lexeme) {
for (int i = 0; reservedWords[i]; i++) {
if (strcmp(reservedWords[i], lexeme) == 0) {
return CONST + i;
}
}
return NONE;
}
TokenCode getSymbolCode(const char *lexeme) {
for (int i = 0; symbols[i]; i++) {
if (strcmp(symbols[i], lexeme) == 0) {
return PLUS + i;
}
}
return NONE;
}
int isLetter(char c) {
return isalpha(c) || c == '_';
}
int isDigit(char c) {
return isdigit(c);
}
int isSymbol(char c) {
return strchr("+-*/().,:;=<>\[\]{}", c) != NULL;
}
int isReservedWord(const char *lexeme) {
return getReservedWordCode(lexeme) != NONE;
}
int isSymbolWord(const char *lexeme) {
return getSymbolCode(lexeme) != NONE;
}
void printToken(Token token) {
printf("%d: %s %s", token.lineNo, token.lexeme, token.type == NONE ? "" : token.type == IDENT ? "IDENT" : token.type == NUMBER ? "NUMBER" : token.type == RESERVED ? "RESERVED" : "SYMBOL");
if (token.type == NUMBER) {
printf(" %d", token.value);
}
printf("\n");
}
Token nextToken(FILE *fp, int *lineNo) {
Token token = {NONE, "", *lineNo, NONE, 0};
int pos = 0;
char c = fgetc(fp);
while (c != EOF) {
if (isspace(c)) {
if (c == '\n') {
(*lineNo)++;
}
c = fgetc(fp);
continue;
}
if (isLetter(c)) {
while (isLetter(c) || isDigit(c)) {
token.lexeme[pos++] = c;
c = fgetc(fp);
}
token.lexeme[pos] = '\0';
ungetc(c, fp);
if (isReservedWord(token.lexeme)) {
token.code = getReservedWordCode(token.lexeme);
token.type = RESERVED;
} else {
token.type = IDENT;
}
return token;
}
if (isDigit(c)) {
while (isDigit(c)) {
token.lexeme[pos++] = c;
c = fgetc(fp);
}
token.lexeme[pos] = '\0';
ungetc(c, fp);
token.code = NUMBER;
token.type = NUMBER;
token.value = atoi(token.lexeme);
return token;
}
if (isSymbol(c)) {
if (c == '+' || c == '-') {
char next = fgetc(fp);
if (next == c || (c == '+' && next == '-') || (c == '-' && next == '+')) {
token.lexeme[pos++] = c;
token.lexeme[pos++] = next;
token.lexeme[pos] = '\0';
token.code = getSymbolCode(token.lexeme);
token.type = SYMBOL;
return token;
} else {
ungetc(next, fp);
}
}
token.lexeme[pos++] = c;
token.lexeme[pos] = '\0';
token.code = getSymbolCode(token.lexeme);
token.type = SYMBOL;
return token;
}
printf("Unrecognized character '%c' in line %d\n", c, *lineNo);
exit(-1);
}
token.code = PERIOD;
token.type = SYMBOL;
return token;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s filename\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("Can't open file %s\n", argv[1]);
return 1;
}
int lineNo = 1;
Token token;
do {
token = nextToken(fp, &lineNo);
printToken(token);
} while (token.code != PERIOD);
fclose(fp);
return 0;
}
```
在这个词法分析器程序中,我们新增了以下扩展功能:
1. 数组功能:新增了`LBRACK`和`RBRACK`两个符号,用于表示数组下标的左右中括号。
2. 记录类型:新增了`RECORD`和`DOT`两个符号,用于表示记录类型和记录类型的成员访问。
3. for循环语句:新增了`FOR`, `TO`, `DO`三个关键字,用于表示for循环语句。
4. switch语句:新增了`SWITCH`, `CASE`, `DEFAULT`, `ENDSWITCH`四个关键字,用于表示switch语句。
5. if else语句:在原有的if语句基础上,新增了`ELSE`关键字,用于表示if else语句。
6. 浮点型或其他类型的数据:在原有的数字基础上,可以扩展为浮点型或其他类型的数据。
7. ++、--运算:新增了`INC`和`DEC`两个符号,用于表示++和--运算。
需要注意的是,这只是一个简单的词法分析器程序,还需要在此基础上完成语法分析、语义分析和代码生成等工作才能实现完整的编译器。
使用终端A上的扩展IO口PA3连接DS18B20温度传感器。 每当按键ASW4按下,通过串口上报温度数据一次,温度发送格式: "C:25.26\r\n" 串口发送格式(字符串) 备注: C为大写字母,温度值结果保留小数点后2位有效数字。 串口发送的字符串应包含换行、回车符号:"\r\n"。 通过USART3的USB转串口功能实现,波特率设置为9600 bps。
这是一个需要编写嵌入式程序的问题,需要使用编程语言和相应的开发环境来完成。以下是一个基于STM32F4开发板的C语言代码示例,实现了该功能:
```c
#include "stm32f4xx.h"
#include <stdio.h>
#include <string.h>
#define DS18B20_PIN GPIO_Pin_3
#define DS18B20_GPIO GPIOA
void delay_us(uint32_t us)
{
for (uint32_t i = 0; i < us * 8; i++);
}
void ds18b20_init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
}
void ds18b20_write_bit(uint8_t bit)
{
GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(2);
if (bit)
{
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(60);
}
else
{
delay_us(60);
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
}
delay_us(2);
}
void ds18b20_write_byte(uint8_t byte)
{
for (uint8_t i = 0; i < 8; i++)
{
ds18b20_write_bit(byte & 0x01);
byte >>= 1;
}
}
uint8_t ds18b20_read_bit(void)
{
GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(2);
GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN);
delay_us(12);
GPIO_PinState state = GPIO_ReadInputDataBit(DS18B20_GPIO, DS18B20_PIN);
delay_us(50);
return state;
}
uint8_t ds18b20_read_byte(void)
{
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++)
{
byte |= ds18b20_read_bit() << i;
}
return byte;
}
float ds18b20_read_temperature(void)
{
ds18b20_init();
ds18b20_write_byte(0xCC);
ds18b20_write_byte(0x44);
while (!ds18b20_read_bit());
ds18b20_init();
ds18b20_write_byte(0xCC);
ds18b20_write_byte(0xBE);
uint16_t raw = ds18b20_read_byte() | (ds18b20_read_byte() << 8);
int16_t temp = (int16_t)raw / 16;
float dec = (float)(raw & 0x0F) / 16;
float temperature = (float)temp + dec;
return temperature;
}
void usart3_init(uint32_t baudrate)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_Cmd(USART3, ENABLE);
}
void usart3_send_string(char* str)
{
while (*str)
{
USART_SendData(USART3, *str++);
while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}
}
int main(void)
{
usart3_init(9600);
while (1)
{
if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == RESET)
{
float temperature = ds18b20_read_temperature();
char str[16];
sprintf(str, "C:%.2f\r\n", temperature);
usart3_send_string(str);
while (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == RESET);
}
}
}
```
该程序首先初始化了DS18B20温度传感器和USART3串口。在主循环中,程序不断读取ASW4按键状态,如果按键被按下,则读取温度传感器的温度值,并通过USART3串口发送给上位机。发送的字符串格式为"C:25.26\r\n",其中温度值使用sprintf函数转换为字符串格式。发送完成后,程序等待ASW4按键释放。
阅读全文